<<sound "music" "music.main" true>><div class="ageGate"><div class="ageGateBadge">18+</div><div class="ageGateTitle">Adult Content Warning</div><div class="ageGateSub">This game contains <strong>sexually explicit content</strong> intended for adults only.<br>If you are <strong>under the age of 20</strong>, you must leave immediately.</div><div class="ageGateCard"><div class="ageGateCardLabel"><span class="ageGateCardBar"></span>CONSENT & DISCLAIMER</div><div class="ageGateCardText">All characters represented in this game, both in-game and in real life, are portrayed by <strong>consenting adult actresses</strong>. All depicted individuals are <strong>legal of age or older</strong>, and all interactions shown are fictional, consensual, and created for entertainment purposes only.</div></div><div class="ageGateSmall">By pressing <strong>Confirm</strong>, you declare that you are at least <strong>20 years old</strong> <em>(or the legal age to view pornographic content in your country)</em> and that you are responsible for complying with the laws of your jurisdiction.</div><div class="ageGateBtns"><span class="ageGateBtn ageGateBtnConfirm">[[Yes, I confirm|Confirm 2]]</span><a class="ageGateBtn ageGateBtnAlt" href="javascript:window.close();" onclick="window.open('','_self').close();">No, I am under 20</a></div><div class="ageGateNote">Proceed only if you are comfortable with explicit adult themes.</div></div><style>
.ageGate{min-height:80vh;display:flex;flex-direction:column;justify-content:center;align-items:center;text-align:center;padding:32px 20px;gap:18px;}
.ageGateBadge{display:inline-flex;align-items:center;justify-content:center;width:54px;height:54px;border-radius:999px;background:rgba(230,87,99,.12);border:1px solid rgba(230,87,99,.35);color:rgb(230,87,99);font-size:16px;font-weight:950;letter-spacing:.06em;box-shadow:0 0 28px rgba(230,87,99,.12);}
.ageGateTitle{font-size:36px;font-weight:950;letter-spacing:.02em;text-transform:uppercase;color:rgba(255,255,255,.96);line-height:1.05;margin:0;}
.ageGateSub{font-size:16px;line-height:1.6;max-width:620px;color:rgba(255,255,255,.65);margin:0;}
.ageGateCard{max-width:640px;width:100%;background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.08);border-radius:14px;padding:18px 22px;text-align:left;position:relative;overflow:hidden;}
.ageGateCard:before{content:"";position:absolute;inset:0;background:radial-gradient(600px 300px at 100% 0%, rgba(230,87,99,.06), transparent 70%);pointer-events:none;}
.ageGateCardAlt:before{background:radial-gradient(600px 300px at 0% 100%, rgba(99,140,230,.06), transparent 70%) !important;}
.ageGateCardLabel{display:flex;align-items:center;gap:10px;font-size:11px;font-weight:950;letter-spacing:.14em;text-transform:uppercase;color:rgba(255,255,255,.88);margin-bottom:10px;}
.ageGateCardBar{width:2px;height:13px;background:rgb(230,87,99);border-radius:999px;flex:0 0 auto;}
.ageGateCardBarBlue{background:rgb(99,140,230);}
.ageGateCardText{font-size:14px;line-height:1.6;color:rgba(255,255,255,.60);}
.ageGateSmall{font-size:13px;line-height:1.65;max-width:580px;color:rgba(255,255,255,.45);margin:0;}
.ageGateBtns{display:flex;flex-wrap:wrap;gap:12px;justify-content:center;margin-top:4px;}
.ageGateBtn{display:inline-flex;align-items:center;justify-content:center;border-radius:10px;font-size:14px;font-weight:900;letter-spacing:.08em;text-transform:uppercase;cursor:pointer;user-select:none;transition:filter .12s, background .12s, border-color .12s;}
.ageGateBtnConfirm a{display:inline-flex;align-items:center;justify-content:center;padding:12px 32px;border-radius:10px;border:1px solid rgba(230,87,99,.55);background:rgba(230,87,99,.14);color:rgb(230,87,99);font-size:14px;font-weight:900;letter-spacing:.08em;text-transform:uppercase;text-decoration:none;transition:filter .12s, background .12s;}
.ageGateBtnConfirm a:hover{background:rgba(230,87,99,.22);filter:brightness(1.08);}
.ageGateBtnAlt{padding:12px 32px;border:1px solid rgba(255,255,255,.10);background:rgba(255,255,255,.04);color:rgba(255,255,255,.50);text-decoration:none;}
.ageGateBtnAlt:hover{background:rgba(255,255,255,.08);border-color:rgba(255,255,255,.18);color:rgba(255,255,255,.70);}
.ageGateNote{font-size:12px;color:rgba(255,255,255,.25);margin:0;}
</style><<sound "music" "music.main" true>><div class="nameSetup"><div class="nameSetupBadge">👤</div><div class="nameSetupTitle">Create Your Profile</div><div class="nameSetupSub">Choose how you will be known in this world.</div><div class="nameSetupFields"><div class="nameSetupRow"><div class="nameSetupLabel"><span class="nameSetupLabelBar"></span>First Name</div><<textbox "$MCPlayer.firstname" "" autofocus>><<if $MCPlayer.firstname is "">><<set $MCPlayer.firstname to "Tom">><</if>></div><div class="nameSetupRow"><div class="nameSetupLabel"><span class="nameSetupLabelBar"></span>Last Name</div><<textbox "$MCPlayer.lastname" "">><<if $MCPlayer.lastname is "">><<set $MCPlayer.lastname to "Gooner">><</if>></div><div class="nameSetupRow"><div class="nameSetupLabel"><span class="nameSetupLabelBar"></span>Gaming Nickname</div><<textbox "$PlayerCS2.username" "">><<if $PlayerCS2.username is "">><<set $PlayerCS2.username to "xX_N4m3Us3rPro_Xx">><</if>></div></div><div class="nameSetupActions"><<button [[Confirm|Confirm 3]]>><</button>><<button [[Back|Confirm 1]]>><</button>></div></div><style>
.nameSetup{min-height:75vh;display:flex;flex-direction:column;justify-content:center;align-items:center;text-align:center;padding:32px 20px;gap:20px;}
.nameSetupBadge{display:inline-flex;align-items:center;justify-content:center;width:54px;height:54px;border-radius:999px;background:rgba(230,87,99,.12);border:1px solid rgba(230,87,99,.35);font-size:22px;box-shadow:0 0 28px rgba(230,87,99,.12);}
.nameSetupTitle{font-size:36px;font-weight:950;letter-spacing:.02em;color:rgba(255,255,255,.96);line-height:1.05;margin:0;}
.nameSetupSub{font-size:14px;color:rgba(255,255,255,.40);margin:0;}
.nameSetupFields{width:100%;max-width:520px;display:flex;flex-direction:column;gap:14px;background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.08);border-radius:14px;padding:22px 24px;position:relative;overflow:hidden;}
.nameSetupFields:before{content:"";position:absolute;inset:0;background:radial-gradient(600px 300px at 100% 0%, rgba(230,87,99,.05), transparent 70%);pointer-events:none;}
.nameSetupRow{display:flex;flex-direction:column;gap:7px;text-align:left;}
.nameSetupLabel{display:flex;align-items:center;gap:8px;font-size:11px;font-weight:950;letter-spacing:.14em;text-transform:uppercase;color:rgba(255,255,255,.88);}
.nameSetupLabelBar{width:2px;height:13px;background:rgb(230,87,99);border-radius:999px;flex:0 0 auto;}
.nameSetup input[type="text"]{width:100%;padding:10px 14px;border-radius:8px;border:1px solid rgba(255,255,255,.10);background:rgba(255,255,255,.05);color:rgba(255,255,255,.90);outline:none;box-sizing:border-box;font-size:14px;font-weight:700;transition:border-color .15s, box-shadow .15s;}
.nameSetup input[type="text"]:focus{border-color:rgba(230,87,99,.45);box-shadow:0 0 0 3px rgba(230,87,99,.08);}
.nameSetupActions{display:flex;gap:12px;margin-top:4px;}
.nameSetupActions button:first-child{padding:12px 40px;border-radius:10px;border:1px solid rgba(230,87,99,.55);background:rgba(230,87,99,.14);color:rgb(230,87,99);font-size:14px;font-weight:900;letter-spacing:.08em;text-transform:uppercase;cursor:pointer;transition:background .12s, filter .12s;}
.nameSetupActions button:first-child:hover{background:rgba(230,87,99,.22);filter:brightness(1.08);}
.nameSetupActions button:last-child{padding:12px 40px;border-radius:10px;border:1px solid rgba(255,255,255,.10);background:rgba(255,255,255,.04);color:rgba(255,255,255,.50);font-size:14px;font-weight:900;letter-spacing:.08em;text-transform:uppercase;cursor:pointer;transition:background .12s;}
.nameSetupActions button:last-child:hover{background:rgba(255,255,255,.08);color:rgba(255,255,255,.70);}
</style><<sound "music" "music.main" true>><div class="welcomeWrap"><div class="welcomeBadge">✦</div><div class="welcomeTitle">Welcome</div><div class="welcomeCard"><div class="welcomeCardLabel"><span class="welcomeCardBar"></span>YOUR IDENTITY</div><div class="welcomeCardText">Welcome, <strong class="welcomeAccent"><<print $MCPlayer.firstname>> <<print $MCPlayer.lastname>></strong>, also known online as <strong class="welcomeAccent"><<print $PlayerCS2.username>></strong>.</div></div><div class="welcomeSub">A whole new world is opening up to you. You will be able to do whatever you want, whenever you want, with whoever you want.</div><div class="welcomeSub welcomeSmall">Have fun exploring, meeting new people, and seducing the different characters you will run into along the way. Good luck, and enjoy the game.</div><div class="welcomeActions"><span class="welcomeBtnConfirm">[[Start|MCBedroom]]</span><span class="welcomeBtnAlt">[[Back|Confirm 2]]</span></div></div><<set $SpectatorsThePit = random(50)>><<set $SpectatorsThePit += 25>><style>
.welcomeWrap{min-height:75vh;display:flex;flex-direction:column;justify-content:center;align-items:center;text-align:center;padding:32px 20px;gap:18px;}
.welcomeBadge{display:inline-flex;align-items:center;justify-content:center;width:54px;height:54px;border-radius:999px;background:rgba(230,87,99,.12);border:1px solid rgba(230,87,99,.35);color:rgb(230,87,99);font-size:22px;font-weight:950;box-shadow:0 0 28px rgba(230,87,99,.12);}
.welcomeTitle{font-size:36px;font-weight:950;letter-spacing:.02em;color:rgba(255,255,255,.96);line-height:1.05;margin:0;}
.welcomeCard{max-width:580px;width:100%;background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.08);border-radius:14px;padding:18px 22px;text-align:left;position:relative;overflow:hidden;}
.welcomeCard:before{content:"";position:absolute;inset:0;background:radial-gradient(600px 300px at 100% 0%, rgba(230,87,99,.06), transparent 70%);pointer-events:none;}
.welcomeCardLabel{display:flex;align-items:center;gap:8px;font-size:11px;font-weight:950;letter-spacing:.14em;text-transform:uppercase;color:rgba(255,255,255,.88);margin-bottom:10px;}
.welcomeCardBar{width:2px;height:13px;background:rgb(230,87,99);border-radius:999px;flex:0 0 auto;}
.welcomeCardText{font-size:15px;line-height:1.65;color:rgba(255,255,255,.60);}
.welcomeAccent{color:rgba(255,255,255,.92);font-weight:900;}
.welcomeSub{font-size:15px;line-height:1.65;max-width:560px;color:rgba(255,255,255,.50);margin:0;}
.welcomeSmall{font-size:13px;color:rgba(255,255,255,.35);}
.welcomeActions{display:flex;gap:12px;flex-wrap:wrap;justify-content:center;margin-top:4px;}
.welcomeActions a{display:inline-flex;align-items:center;justify-content:center;text-decoration:none;}
.welcomeBtnConfirm a{display:inline-flex;align-items:center;justify-content:center;padding:12px 40px;border-radius:10px;border:1px solid rgba(230,87,99,.55);background:rgba(230,87,99,.14);color:rgb(230,87,99);font-size:14px;font-weight:900;letter-spacing:.08em;text-transform:uppercase;text-decoration:none;transition:background .12s, filter .12s;}
.welcomeBtnConfirm a:hover{background:rgba(230,87,99,.22);filter:brightness(1.08);}
.welcomeBtnAlt a{padding:12px 40px;border-radius:10px;border:1px solid rgba(255,255,255,.10);background:rgba(255,255,255,.04);color:rgba(255,255,255,.50);font-size:14px;font-weight:900;letter-spacing:.08em;text-transform:uppercase;cursor:pointer;transition:background .12s;}
.welcomeBtnAlt a:hover{background:rgba(255,255,255,.08);color:rgba(255,255,255,.70);}
</style><<if $AutoSaveCheck == true>><<AutoSaveStart>><<set $AutoSaveCheck = false>><</if>><<script>>
setTimeout(function() {
TutorialEngine.init("passages");
}, 100);
<</script>><<sound "music" "music.music" true>><<sound "bg" "bg.empty" true>><<bgpersist true>><<passagebg>><<if $Time !== 3>><img src="assets/img/misc/home/mcbedroom.webp"><<else>><img src="assets/img/misc/home/mcbedroomnight.webp"><</if>><</passagebg>>
<div class="BottomUiBarCustom">
<div id="tutorial-action"><<BottomButton "Action">>[[💤 Sleep|Sleep]]
[[💻 Computer|MCPC]]<</BottomButton>></div><<if $MayorStoryInfo3 == true and $MayorStoryInfo4 == false>><br><<BottomButton "Decision">><<link "💭 Read the document">><<goto "MayorStory7">><</link>><</BottomButton>><</if>>
<div id="tutorial-move"><<BottomButton "Move">><<if $StartStory == true>>[[🚪 Leave the bedroom|HomeCorridor]]<<else>><em>I should check my emails</em><</if>> <</BottomButton>></div>
</div>
<<set $InMainMenu = false>><<pauseguard false>><<set $InteractInInterior = true>><<set $ShowTopUiBar = true>><<set $ShowBottomUiBar = true>><<if $NPCLandladyChapter5 is undefined>><<set $NPCLandladyChapter5 = false>><</if>><<if $NPCBestFriendSMSTalklvl2DayInt is undefined>><<set $NPCBestFriendSMSTalklvl2DayInt = -9999>><</if>><<if $NPCBestFriendSMSSend2 is undefined>><<set $NPCBestFriendSMSSend2 = false>><</if>><<if $NPCBestFriendSMSTalklvl2 is undefined>><<set $NPCBestFriendSMSTalklvl2 = false>><</if>><<sound "music" "music.music" true>><<bgpause>><<passagebg>><<if $PCos.img is 1>><img src="assets/img/misc/MCPC/os1.gif"/><<elseif $PCos.img is 2>><img src="assets/img/misc/MCPC/os2.gif"/><<elseif $PCos.img is 3>><img src="assets/img/misc/MCPC/os3.gif"/><</if>><</passagebg>>
<div class="BottomUiBarCustom">
<<BottomButton "Action">>[[🎮 Steam|Play]]
[[🌐 Internet|Internet]]
[[🎙️ Discord|Discord]]<<if $SpycamSoftware == true>><br>[[📷 Spycam Software|SpycamSoftware]]<</if>><</BottomButton>>
<<BottomButton "Inspection">>[[🧩 PC Component|PC_Component]]<</BottomButton>>
<<BottomButton "Move">><<return [[⏻ Shutdown|MCBedroom]]>><</BottomButton>>
</div><<sound "music" "music.music" true>><<sound "bg" "bg.empty" true>><<passagebg>><<if $Time !== 3>><img src="assets/img/misc/home/corridor.webp"/><<else>><img src="assets/img/misc/home/corridornight.webp"/><</if>><</passagebg>>
<div class="BottomUiBarCustom">
<<BottomButton "Move">>[[🛏️ My bedroom|MCBedroom]]
[[🚿 Bathroom|Bathroom]]
<<link "🛏️ <<=$NPCHousemateFemale.name>> bedroom">><<goto "HousemateFemaleBedroom">><</link>>
<<link "🛏️ <<=$NPCHousemateMale.name>> bedroom">><<goto "HousemateMaleBedroom">><</link>>
[[🛏️ Main bedroom|MainBedroom]]
[[⬇️ Go downstairs|HomeEntrance]]<</BottomButton>>
</div><<sound "music" "music.music" true>><<passagebg>><<set _MCsleep = random(19)>><<if _MCsleep is 0>>
<img src="assets/img/sleep/1.webp"/>
<<elseif _MCsleep is 1>>
<img src="assets/img/sleep/2.webp"/>
<<elseif _MCsleep is 2>>
<img src="assets/img/sleep/3.webp"/>
<<elseif _MCsleep is 3>>
<img src="assets/img/sleep/4.webp"/>
<<elseif _MCsleep is 4>>
<img src="assets/img/sleep/5.webp"/>
<<elseif _MCsleep is 5>>
<img src="assets/img/sleep/6.webp"/>
<<elseif _MCsleep is 6>>
<img src="assets/img/sleep/7.webp"/>
<<elseif _MCsleep is 7>>
<img src="assets/img/sleep/8.webp"/>
<<elseif _MCsleep is 8>>
<img src="assets/img/sleep/9.webp"/>
<<elseif _MCsleep is 9>>
<img src="assets/img/sleep/10.webp"/>
<<elseif _MCsleep is 10>>
<img src="assets/img/sleep/11.webp"/>
<<elseif _MCsleep is 11>>
<img src="assets/img/sleep/12.webp"/>
<<elseif _MCsleep is 12>>
<img src="assets/img/sleep/13.webp"/>
<<elseif _MCsleep is 13>>
<img src="assets/img/sleep/14.webp"/>
<<elseif _MCsleep is 14>>
<img src="assets/img/sleep/15.webp"/>
<<elseif _MCsleep is 15>>
<img src="assets/img/sleep/16.webp"/>
<<elseif _MCsleep is 16>>
<img src="assets/img/sleep/17.webp"/>
<<elseif _MCsleep is 17>>
<img src="assets/img/sleep/18.webp"/>
<<elseif _MCsleep is 18>>
<img src="assets/img/sleep/19.webp"/>
<<elseif _MCsleep is 19>>
<img src="assets/img/sleep/0.webp"/>
<</if>><</passagebg>><<if _MCsleep is 0>>
<img src="assets/img/sleep/1.webp"/>
<<elseif _MCsleep is 1>>
<img src="assets/img/sleep/2.webp"/>
<<elseif _MCsleep is 2>>
<img src="assets/img/sleep/3.webp"/>
<<elseif _MCsleep is 3>>
<img src="assets/img/sleep/4.webp"/>
<<elseif _MCsleep is 4>>
<img src="assets/img/sleep/5.webp"/>
<<elseif _MCsleep is 5>>
<img src="assets/img/sleep/6.webp"/>
<<elseif _MCsleep is 6>>
<img src="assets/img/sleep/7.webp"/>
<<elseif _MCsleep is 7>>
<img src="assets/img/sleep/8.webp"/>
<<elseif _MCsleep is 8>>
<img src="assets/img/sleep/9.webp"/>
<<elseif _MCsleep is 9>>
<img src="assets/img/sleep/10.webp"/>
<<elseif _MCsleep is 10>>
<img src="assets/img/sleep/11.webp"/>
<<elseif _MCsleep is 11>>
<img src="assets/img/sleep/12.webp"/>
<<elseif _MCsleep is 12>>
<img src="assets/img/sleep/13.webp"/>
<<elseif _MCsleep is 13>>
<img src="assets/img/sleep/14.webp"/>
<<elseif _MCsleep is 14>>
<img src="assets/img/sleep/15.webp"/>
<<elseif _MCsleep is 15>>
<img src="assets/img/sleep/16.webp"/>
<<elseif _MCsleep is 16>>
<img src="assets/img/sleep/17.webp"/>
<<elseif _MCsleep is 17>>
<img src="assets/img/sleep/18.webp"/>
<<elseif _MCsleep is 18>>
<img src="assets/img/sleep/19.webp"/>
<<elseif _MCsleep is 19>>
<img src="assets/img/sleep/0.webp"/>
<</if>><<InformationUiPopUp "What a beautiful dream, isn't it?">><em>+<<=$EnergyMax>> Energy</em><<set $Energy = $EnergyMax>>
<em>+<<=$PsychicPowerMax>> Psychic Power</em><<set $PsychicPower = $PsychicPowerMax>><<if $Heal < $HealMax>><br><em>+25 Health</em><<set $Heal += 25>><</if>><<if $Stress > $StressMin>><br><em>-2 Stress</em><<set $Stress -= 2>><</if>><<set $SpectatorsThePit = random(25,50)>><<set $SpectatorsThePit += 25>><<set $Day++>><<set $Time = 0>><<set $Hour = 0>><<set $TravelPerTime = 0>>
<</InformationUiPopUp>><<if $SedativesGlassWater == true or $NPCLandlordSleepDrug == true>><<set $SedativesBought = false>><<set $NPCLandladyTalkCorruption5DayInt = -9999>><<set $NPCLandladyTalkCorruptionSend5 = false>><<set $SedativesDeliveredWaiting = false>><<set $LandladyChapter6Story2Played = false>><<set $SedativesDelivered = false>><<set $LandladyChapter6Story3Played = false>><<set $SedativesGlassWater = false>><<set $LandladyChapter6Story4Played = false>><<set $NPCLandlordSleepDrug = false>><<if $Inventory.glasswater and $Inventory.glasswater.qty >= 1>><<run delete State.variables.Inventory.glasswater>><</if>><</if>>
<div class="BottomUiBarCustom">
<<BottomButton "Move">><<link "🥱 Wake up">><<if $NPCLandlady.met == true and $NPCLandlady.lvl <= 0>><<set $FromOtherPlace = true>><<set $ReturnTo = "HomeKitchen">><<set $ActiveNPC = $NPCLandlady>><<goto "Talk.Landlady">><<else>><<goto "MCBedroom">><</if>><</link>><<set $ShowerDayTime = false, $FitnessDayTime = false, $MedidationDayTime = false>><<set $AutoSaveCheck = true>><</BottomButton>>
</div>
<<script>>
(function(){
var V = State.variables;
if(!V.SpycamUnlocked) V.SpycamUnlocked = {};
if(V.SpycamLastUnlockDay === V.Day) return;
V.SpycamUnlockedToday = 0;
var activeCams = [];
for(var ck in V.Spycam){ if(V.Spycam[ck]) activeCams.push(ck); }
if(activeCams.length === 0){
V.SpycamLastUnlockDay = V.Day;
return;
}
var storageLvl = V.PCstockage.img;
var maxStorage = 5 + Math.max(0, storageLvl - 1) * 5;
maxStorage = Math.min(15, maxStorage);
if(storageLvl < 1) maxStorage = 5;
var shuffled = activeCams.slice();
for(var i = shuffled.length - 1; i > 0; i--){
var j = Math.floor(Math.random() * (i + 1));
var tmp = shuffled[i]; shuffled[i] = shuffled[j]; shuffled[j] = tmp;
}
var unlockedToday = 0;
for(var k = 0; k < shuffled.length; k++){
if(unlockedToday >= 2) break;
var camK = shuffled[k];
var totalCount = 0;
for(var c2 in V.SpycamUnlocked){
if(V.Spycam[c2]) totalCount += (V.SpycamUnlocked[c2] || []).length;
}
if(totalCount >= maxStorage) break;
var camMax = (setup.SpycamMaxImages && setup.SpycamMaxImages[camK]) || 0;
if(camMax < 1) continue;
if(Math.random() < 0.5){
var alreadyOwned = (V.SpycamUnlocked[camK] || []).slice();
var candidates = [];
for(var n = 1; n <= camMax; n++){
if(alreadyOwned.indexOf(n) === -1) candidates.push(n);
}
if(candidates.length > 0){
var pickedNum = candidates[Math.floor(Math.random() * candidates.length)];
if(!V.SpycamUnlocked[camK]) V.SpycamUnlocked[camK] = [];
V.SpycamUnlocked[camK].push(pickedNum);
unlockedToday++;
V.SpycamUnlockedToday = (V.SpycamUnlockedToday || 0) + 1;
}
}
}
V.SpycamLastUnlockDay = V.Day;
})();
<</script>><<set $ShowTopUiBar = true>><<set $ShowBottomUiBar = true>><<sound "music" "music.music" true>><<passagebg>><img src="assets/img/misc/MCPC/play/steam.webp"/><</passagebg>>
<div class="BottomUiBarCustom">
<<BottomButton "Action">>[[🔫 CounterStrike 2|PlayCS2]]
[[🧱 Minecraft|PlayMC]]
/*<<link "🔫 CS2 Simulator">><<SetReturnTo>><<goto "CS2.HUB">><</link>>*/<</BottomButton>>
<<BottomButton "Move">><<return [[↩️ Close Steam|MCPC]]>><</BottomButton>>
</div><<sound "music" "music.music" true>><<passagebg>><img src="assets/img/misc/MCPC/internet/searchgoogle.gif"/><</passagebg>>
<div class="BottomUiBarCustom">
<<BottomButton "Action">>[[📧 Email|Email]]
[[🔞 Porn|Porn]]<</BottomButton>><<if $SearchWork == false or $UniversityJobListing == true or ($Story4_2Finish == true and $Story4_3Finish == false) or ($NPCLandlady.lvl == 5 and $SedativesBought == false)>><br><<BottomButton "Decision">><<if $SearchWork == false>><<link "💼 Look for a job">><<goto "SearchWork1">><</link>><</if>><<if $UniversityJobListing == true>><br><<link "💼 Look at the University Job Posting">><<goto "UniversityWork2">><</link>><</if>><<if $Story4_2Finish == true and $SpycamSoftware == false>><<link "🔍 Find spycam software">><<goto "SpycamSoftware1">><</link>><</if>><<if $NPCLandlady.lvl == 5 and $SedativesBought == false>><<link "🔍 Find sleeping medication">><<goto "LandladyChapter6Story1">><</link>><</if>><</BottomButton>><</if>>
<<BottomButton "Move">><<return [[↩️ Close Web|MCPC]]>><</BottomButton>>
</div><<sound "music" "music.music" true>><<set $qualityPC = $PCMotherboard.img + $PCcpu.img + $PCgpu.img + $PCram.img + $PCstockage.img + $PCos.img>><<set $qualitySetup = $PCscreen.img + $PCkeyboard.img + $PCmouse.img + $PCheadset.img + $PCmicrophone.img + $PCcamera.img>><<set _mbExt = $PCMotherboard.img === 2 ? "jpg" : "webp">><<set _cpuExt = $PCcpu.img === 1 ? "webp" : "jpg">><<set _gpuExt = $PCgpu.img === 3 ? "jpg" : "webp">><<set _ramExt = $PCram.img === 2 ? "jpg" : "webp">><<set _stExt = $PCstockage.img === 1 ? "jpg" : "webp">><<set _kbExt = $PCkeyboard.img === 3 ? "webp" : "jpg">><<set _hsExt = $PCheadset.img === 3 ? "webp" : "jpg">><style>#mcpc-app{--red:rgb(230,87,99);--yellow:#e6c357;--green:rgb(127,199,164);--surface:rgba(255,255,255,.04);--surface-hover:rgba(255,255,255,.07);--border:rgba(255,255,255,.10);--border-strong:rgba(255,255,255,.18);--text:rgba(255,255,255,.95);--text-dim:rgba(255,255,255,.65);--text-muted:rgba(255,255,255,.40);color:var(--text);padding:16px;max-width:1100px;margin:0 auto;}#mcpc-app *{box-sizing:border-box;}.mcpc-scores{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-bottom:22px;}.mcpc-score-card{background:var(--surface);border:1px solid var(--border-strong);border-radius:12px;padding:16px 18px;display:flex;align-items:center;gap:16px;}.mcpc-score-icon{font-size:calc(28px + var(--font-boost,0px));flex:0 0 auto;}.mcpc-score-body{display:flex;flex-direction:column;gap:5px;min-width:0;flex:1;}.mcpc-score-label{font-size:calc(14px + var(--font-boost,0px));font-weight:800;letter-spacing:.08em;text-transform:uppercase;color:var(--text-dim);}.mcpc-score-val{font-size:calc(24px + var(--font-boost,0px));font-weight:950;color:var(--text);font-family:'JetBrains Mono','Fira Code',Consolas,monospace;line-height:1;}.mcpc-score-sub{font-size:calc(14px + var(--font-boost,0px));color:var(--text-muted);font-weight:700;}.mcpc-cols{display:grid;grid-template-columns:1fr 1fr;gap:16px;}.mcpc-panel{background:var(--surface);border:1px solid var(--border);border-radius:14px;overflow:hidden;}.mcpc-panel-header{padding:14px 18px;border-bottom:1px solid var(--border);display:flex;align-items:center;gap:10px;background:rgba(255,255,255,.02);}.mcpc-panel-icon{font-size:calc(18px + var(--font-boost,0px));}.mcpc-panel-title{font-size:calc(15px + var(--font-boost,0px));font-weight:950;letter-spacing:.08em;text-transform:uppercase;color:var(--text);}.mcpc-components{padding:6px;}.mcpc-row{display:flex;align-items:center;gap:14px;padding:10px 12px;border-radius:9px;transition:background .14s;}.mcpc-row:hover{background:var(--surface-hover);}.mcpc-row+.mcpc-row{border-top:1px solid rgba(255,255,255,.06);}.mcpc-thumb{width:56px;height:56px;flex:0 0 56px;border-radius:9px;background:rgba(0,0,0,.50);border:1px solid var(--border);display:flex;align-items:center;justify-content:center;overflow:hidden;}.mcpc-thumb img{width:100% !important;height:100% !important;object-fit:contain !important;display:block !important;}.mcpc-thumb-empty{font-size:calc(24px + var(--font-boost,0px));opacity:.25;}.mcpc-info{flex:1 1 auto;min-width:0;display:flex;flex-direction:column;gap:3px;}.mcpc-info-label{font-size:calc(14px + var(--font-boost,0px));font-weight:900;letter-spacing:.08em;text-transform:uppercase;color:var(--text-dim);}.mcpc-info-name{font-size:calc(14px + var(--font-boost,0px));font-weight:700;color:var(--text);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;line-height:1.3;}.mcpc-info-name.is-empty{color:var(--text-muted);font-style:italic;}.mcpc-tier{flex:0 0 auto;display:flex;flex-direction:column;align-items:center;gap:4px;}.mcpc-tier-dots{display:flex;flex-direction:column;gap:4px;}.mcpc-tier-dot{width:8px;height:8px;border-radius:999px;background:rgba(255,255,255,.14);border:1px solid rgba(255,255,255,.08);}.mcpc-tier-dot.on-1{background:var(--red);border-color:rgba(230,87,99,.60);box-shadow:0 0 6px rgba(230,87,99,.50);}.mcpc-tier-dot.on-2{background:var(--yellow);border-color:rgba(230,195,87,.60);box-shadow:0 0 6px rgba(230,195,87,.50);}.mcpc-tier-dot.on-3{background:var(--green);border-color:rgba(127,199,164,.60);box-shadow:0 0 6px rgba(127,199,164,.50);}@media(max-width:700px){.mcpc-scores{grid-template-columns:1fr;}.mcpc-cols{grid-template-columns:1fr;}}</style><div id="mcpc-app"><div class="mcpc-scores"><div class="mcpc-score-card"><span class="mcpc-score-icon">🖥️</span><div class="mcpc-score-body"><span class="mcpc-score-label">PC Quality</span><span class="mcpc-score-val">$qualityPC <span class="mcpc-score-sub">/ 18</span></span></div></div><div class="mcpc-score-card"><span class="mcpc-score-icon">🎮</span><div class="mcpc-score-body"><span class="mcpc-score-label">Setup Quality</span><span class="mcpc-score-val">$qualitySetup <span class="mcpc-score-sub">/ 18</span></span></div></div></div><div class="mcpc-cols"><div class="mcpc-panel"><div class="mcpc-panel-header"><span class="mcpc-panel-icon">⚙️</span><span class="mcpc-panel-title">System Unit</span></div><div class="mcpc-components"><div class="mcpc-row"><div class="mcpc-thumb"><<if $PCMotherboard.img gte 1>><<= '<img src="assets/img/misc/MCPC/motherboard' + $PCMotherboard.img + '.' + _mbExt + '">'>><<else>><span class="mcpc-thumb-empty">📋</span><</if>></div><div class="mcpc-info"><div class="mcpc-info-label">Motherboard</div><div class="mcpc-info-name<<if $PCMotherboard.img is 0>> is-empty<</if>>"><<print $PCMotherboard.name>></div></div><div class="mcpc-tier"><div class="mcpc-tier-dots"><span class="mcpc-tier-dot<<if $PCMotherboard.img gte 3>> on-3<</if>>"></span><span class="mcpc-tier-dot<<if $PCMotherboard.img gte 2>> on-<<if $PCMotherboard.img gte 3>>3<<else>>2<</if>><</if>>"></span><span class="mcpc-tier-dot<<if $PCMotherboard.img gte 1>> on-<<print $PCMotherboard.img>><</if>>"></span></div></div></div><div class="mcpc-row"><div class="mcpc-thumb"><<if $PCcpu.img gte 1>><<= '<img src="assets/img/misc/MCPC/cpu' + $PCcpu.img + '.' + _cpuExt + '">'>><<else>><span class="mcpc-thumb-empty">🔲</span><</if>></div><div class="mcpc-info"><div class="mcpc-info-label">Processor (CPU)</div><div class="mcpc-info-name<<if $PCcpu.img is 0>> is-empty<</if>>"><<print $PCcpu.name>></div></div><div class="mcpc-tier"><div class="mcpc-tier-dots"><span class="mcpc-tier-dot<<if $PCcpu.img gte 3>> on-3<</if>>"></span><span class="mcpc-tier-dot<<if $PCcpu.img gte 2>> on-<<if $PCcpu.img gte 3>>3<<else>>2<</if>><</if>>"></span><span class="mcpc-tier-dot<<if $PCcpu.img gte 1>> on-<<print $PCcpu.img>><</if>>"></span></div></div></div><div class="mcpc-row"><div class="mcpc-thumb"><<if $PCgpu.img gte 1>><<= '<img src="assets/img/misc/MCPC/gpu' + $PCgpu.img + '.' + _gpuExt + '">'>><<else>><span class="mcpc-thumb-empty">🎴</span><</if>></div><div class="mcpc-info"><div class="mcpc-info-label">Graphics Card (GPU)</div><div class="mcpc-info-name<<if $PCgpu.img is 0>> is-empty<</if>>"><<print $PCgpu.name>></div></div><div class="mcpc-tier"><div class="mcpc-tier-dots"><span class="mcpc-tier-dot<<if $PCgpu.img gte 3>> on-3<</if>>"></span><span class="mcpc-tier-dot<<if $PCgpu.img gte 2>> on-<<if $PCgpu.img gte 3>>3<<else>>2<</if>><</if>>"></span><span class="mcpc-tier-dot<<if $PCgpu.img gte 1>> on-<<print $PCgpu.img>><</if>>"></span></div></div></div><div class="mcpc-row"><div class="mcpc-thumb"><<if $PCram.img gte 1>><<= '<img src="assets/img/misc/MCPC/ram' + $PCram.img + '.' + _ramExt + '">'>><<else>><span class="mcpc-thumb-empty">💾</span><</if>></div><div class="mcpc-info"><div class="mcpc-info-label">Memory (RAM)</div><div class="mcpc-info-name<<if $PCram.img is 0>> is-empty<</if>>"><<print $PCram.name>></div></div><div class="mcpc-tier"><div class="mcpc-tier-dots"><span class="mcpc-tier-dot<<if $PCram.img gte 3>> on-3<</if>>"></span><span class="mcpc-tier-dot<<if $PCram.img gte 2>> on-<<if $PCram.img gte 3>>3<<else>>2<</if>><</if>>"></span><span class="mcpc-tier-dot<<if $PCram.img gte 1>> on-<<print $PCram.img>><</if>>"></span></div></div></div><div class="mcpc-row"><div class="mcpc-thumb"><<if $PCstockage.img gte 1>><<= '<img src="assets/img/misc/MCPC/stockage' + $PCstockage.img + '.' + _stExt + '">'>><<else>><span class="mcpc-thumb-empty">🗄️</span><</if>></div><div class="mcpc-info"><div class="mcpc-info-label">Storage</div><div class="mcpc-info-name<<if $PCstockage.img is 0>> is-empty<</if>>"><<print $PCstockage.name>></div></div><div class="mcpc-tier"><div class="mcpc-tier-dots"><span class="mcpc-tier-dot<<if $PCstockage.img gte 3>> on-3<</if>>"></span><span class="mcpc-tier-dot<<if $PCstockage.img gte 2>> on-<<if $PCstockage.img gte 3>>3<<else>>2<</if>><</if>>"></span><span class="mcpc-tier-dot<<if $PCstockage.img gte 1>> on-<<print $PCstockage.img>><</if>>"></span></div></div></div><div class="mcpc-row"><div class="mcpc-thumb"><<if $PCos.img gte 1>><<= '<img src="assets/img/misc/MCPC/os' + $PCos.img + '.png">'>><<else>><span class="mcpc-thumb-empty">💿</span><</if>></div><div class="mcpc-info"><div class="mcpc-info-label">Operating System</div><div class="mcpc-info-name<<if $PCos.img is 0>> is-empty<</if>>"><<print $PCos.name>></div></div><div class="mcpc-tier"><div class="mcpc-tier-dots"><span class="mcpc-tier-dot<<if $PCos.img gte 3>> on-3<</if>>"></span><span class="mcpc-tier-dot<<if $PCos.img gte 2>> on-<<if $PCos.img gte 3>>3<<else>>2<</if>><</if>>"></span><span class="mcpc-tier-dot<<if $PCos.img gte 1>> on-<<print $PCos.img>><</if>>"></span></div></div></div></div></div><div class="mcpc-panel"><div class="mcpc-panel-header"><span class="mcpc-panel-icon">🖱️</span><span class="mcpc-panel-title">Setup & Peripherals</span></div><div class="mcpc-components"><div class="mcpc-row"><div class="mcpc-thumb"><<if $PCscreen.img gte 1>><<= '<img src="assets/img/misc/MCPC/screen' + $PCscreen.img + '.jpg">'>><<else>><span class="mcpc-thumb-empty">🖥️</span><</if>></div><div class="mcpc-info"><div class="mcpc-info-label">Screen</div><div class="mcpc-info-name<<if $PCscreen.img is 0>> is-empty<</if>>"><<print $PCscreen.name>></div></div><div class="mcpc-tier"><div class="mcpc-tier-dots"><span class="mcpc-tier-dot<<if $PCscreen.img gte 3>> on-3<</if>>"></span><span class="mcpc-tier-dot<<if $PCscreen.img gte 2>> on-<<if $PCscreen.img gte 3>>3<<else>>2<</if>><</if>>"></span><span class="mcpc-tier-dot<<if $PCscreen.img gte 1>> on-<<print $PCscreen.img>><</if>>"></span></div></div></div><div class="mcpc-row"><div class="mcpc-thumb"><<if $PCkeyboard.img gte 1>><<= '<img src="assets/img/misc/MCPC/keyboard' + $PCkeyboard.img + '.' + _kbExt + '">'>><<else>><span class="mcpc-thumb-empty">⌨️</span><</if>></div><div class="mcpc-info"><div class="mcpc-info-label">Keyboard</div><div class="mcpc-info-name<<if $PCkeyboard.img is 0>> is-empty<</if>>"><<print $PCkeyboard.name>></div></div><div class="mcpc-tier"><div class="mcpc-tier-dots"><span class="mcpc-tier-dot<<if $PCkeyboard.img gte 3>> on-3<</if>>"></span><span class="mcpc-tier-dot<<if $PCkeyboard.img gte 2>> on-<<if $PCkeyboard.img gte 3>>3<<else>>2<</if>><</if>>"></span><span class="mcpc-tier-dot<<if $PCkeyboard.img gte 1>> on-<<print $PCkeyboard.img>><</if>>"></span></div></div></div><div class="mcpc-row"><div class="mcpc-thumb"><<if $PCmouse.img gte 1>><<= '<img src="assets/img/misc/MCPC/mouse' + $PCmouse.img + '.jpg">'>><<else>><span class="mcpc-thumb-empty">🖱️</span><</if>></div><div class="mcpc-info"><div class="mcpc-info-label">Mouse</div><div class="mcpc-info-name<<if $PCmouse.img is 0>> is-empty<</if>>"><<print $PCmouse.name>></div></div><div class="mcpc-tier"><div class="mcpc-tier-dots"><span class="mcpc-tier-dot<<if $PCmouse.img gte 3>> on-3<</if>>"></span><span class="mcpc-tier-dot<<if $PCmouse.img gte 2>> on-<<if $PCmouse.img gte 3>>3<<else>>2<</if>><</if>>"></span><span class="mcpc-tier-dot<<if $PCmouse.img gte 1>> on-<<print $PCmouse.img>><</if>>"></span></div></div></div><div class="mcpc-row"><div class="mcpc-thumb"><<if $PCheadset.img gte 1>><<= '<img src="assets/img/misc/MCPC/headset' + $PCheadset.img + '.' + _hsExt + '">'>><<else>><span class="mcpc-thumb-empty">🎧</span><</if>></div><div class="mcpc-info"><div class="mcpc-info-label">Headset</div><div class="mcpc-info-name<<if $PCheadset.img is 0>> is-empty<</if>>"><<print $PCheadset.name>></div></div><div class="mcpc-tier"><div class="mcpc-tier-dots"><span class="mcpc-tier-dot<<if $PCheadset.img gte 3>> on-3<</if>>"></span><span class="mcpc-tier-dot<<if $PCheadset.img gte 2>> on-<<if $PCheadset.img gte 3>>3<<else>>2<</if>><</if>>"></span><span class="mcpc-tier-dot<<if $PCheadset.img gte 1>> on-<<print $PCheadset.img>><</if>>"></span></div></div></div><div class="mcpc-row"><div class="mcpc-thumb"><<if $PCmicrophone.img gte 1>><<= '<img src="assets/img/misc/MCPC/microphone' + $PCmicrophone.img + '.jpg">'>><<else>><span class="mcpc-thumb-empty">🎙️</span><</if>></div><div class="mcpc-info"><div class="mcpc-info-label">Microphone</div><div class="mcpc-info-name<<if $PCmicrophone.img is 0>> is-empty<</if>>"><<print $PCmicrophone.name>></div></div><div class="mcpc-tier"><div class="mcpc-tier-dots"><span class="mcpc-tier-dot<<if $PCmicrophone.img gte 3>> on-3<</if>>"></span><span class="mcpc-tier-dot<<if $PCmicrophone.img gte 2>> on-<<if $PCmicrophone.img gte 3>>3<<else>>2<</if>><</if>>"></span><span class="mcpc-tier-dot<<if $PCmicrophone.img gte 1>> on-<<print $PCmicrophone.img>><</if>>"></span></div></div></div><div class="mcpc-row"><div class="mcpc-thumb"><<if $PCcamera.img gte 1>><<= '<img src="assets/img/misc/MCPC/camera' + $PCcamera.img + '.jpg">'>><<else>><span class="mcpc-thumb-empty">📷</span><</if>></div><div class="mcpc-info"><div class="mcpc-info-label">Camera</div><div class="mcpc-info-name<<if $PCcamera.img is 0>> is-empty<</if>>"><<print $PCcamera.name>></div></div><div class="mcpc-tier"><div class="mcpc-tier-dots"><span class="mcpc-tier-dot<<if $PCcamera.img gte 3>> on-3<</if>>"></span><span class="mcpc-tier-dot<<if $PCcamera.img gte 2>> on-<<if $PCcamera.img gte 3>>3<<else>>2<</if>><</if>>"></span><span class="mcpc-tier-dot<<if $PCcamera.img gte 1>> on-<<print $PCcamera.img>><</if>>"></span></div></div></div></div></div></div></div><div class="BottomUiBarCustom"><<BottomButton "Move">><<return [[↩️ Return|MCPC]]>><</BottomButton>></div><<sound "music" "music.music" true>><<passagebg>><img src="assets/img/misc/MCPC/internet/porn/introph.gif"/><</passagebg>>
<div class="BottomUiBarCustom">
<<BottomButton "Choice">>[[🔞 Blowjob|PornBlowjob]]
[[🔞 Soft|PornSoft]]
[[🔞 Anal|PornAnal]]
[[🔞 Hardcore|PornHardcore]]<</BottomButton>>
<<BottomButton "Move">><<return [[↩️ Close PornHub|Internet]]>><</BottomButton>>
</div><<sound "music" "music.music" true>><<passagebg>><<set $PH to random(7)>><<if $PH is 0>>
<img src="assets/img/ph/blowjob/1.webp"/>
<<elseif $PH is 1>>
<img src="assets/img/ph/blowjob/2.webp"/>
<<elseif $PH is 2>>
<img src="assets/img/ph/blowjob/3.webp"/>
<<elseif $PH is 3>>
<img src="assets/img/ph/blowjob/4.webp"/>
<<elseif $PH is 4>>
<img src="assets/img/ph/blowjob/5.webp"/>
<<elseif $PH is 5>>
<img src="assets/img/ph/blowjob/6.webp"/>
<<elseif $PH is 6>>
<img src="assets/img/ph/blowjob/7.webp"/>
<<elseif $PH is 7>>
<img src="assets/img/ph/blowjob/8.webp"/>
<</if>><</passagebg>><<if $PH is 0>>
<img src="assets/img/ph/blowjob/1.webp"/>
<<elseif $PH is 1>>
<img src="assets/img/ph/blowjob/2.webp"/>
<<elseif $PH is 2>>
<img src="assets/img/ph/blowjob/3.webp"/>
<<elseif $PH is 3>>
<img src="assets/img/ph/blowjob/4.webp"/>
<<elseif $PH is 4>>
<img src="assets/img/ph/blowjob/5.webp"/>
<<elseif $PH is 5>>
<img src="assets/img/ph/blowjob/6.webp"/>
<<elseif $PH is 6>>
<img src="assets/img/ph/blowjob/7.webp"/>
<<elseif $PH is 7>>
<img src="assets/img/ph/blowjob/8.webp"/>
<</if>><<set $Excitement++>><<if $Excitement >= 10>><<InformationUiPopUp "You just climaxed">>
<<if $Stress <= $StressMin>><em>Stress already at minimum</em><<elseif $Stress > $StressMin>><em>-5 stress</em><<set $Stress -= 5>><</if>><<set $Energy-->><<set $Excitement = 0>>
<</InformationUiPopUp>><</if>>
<div class="BottomUiBarCustom">
<<BottomButton "Action">>[[🔄 Again|PornBlowjob]]<</BottomButton>>
<<BottomButton "Move">><<return [[↩️ Back|Porn]]>><</BottomButton>>
</div><<sound "music" "music.music" true>><<passagebg>><<set $PH to random(7)>><<if $PH is 0>>
<img src="assets/img/ph/soft/1.webp"/>
<<elseif $PH is 1>>
<img src="assets/img/ph/soft/2.webp"/>
<<elseif $PH is 2>>
<img src="assets/img/ph/soft/3.webp"/>
<<elseif $PH is 3>>
<img src="assets/img/ph/soft/4.webp"/>
<<elseif $PH is 4>>
<img src="assets/img/ph/soft/5.webp"/>
<<elseif $PH is 5>>
<img src="assets/img/ph/soft/6.webp"/>
<<elseif $PH is 6>>
<img src="assets/img/ph/soft/7.webp"/>
<<elseif $PH is 7>>
<img src="assets/img/ph/soft/8.webp"/>
<</if>><</passagebg>><<if $PH is 0>>
<img src="assets/img/ph/soft/1.webp"/>
<<elseif $PH is 1>>
<img src="assets/img/ph/soft/2.webp"/>
<<elseif $PH is 2>>
<img src="assets/img/ph/soft/3.webp"/>
<<elseif $PH is 3>>
<img src="assets/img/ph/soft/4.webp"/>
<<elseif $PH is 4>>
<img src="assets/img/ph/soft/5.webp"/>
<<elseif $PH is 5>>
<img src="assets/img/ph/soft/6.webp"/>
<<elseif $PH is 6>>
<img src="assets/img/ph/soft/7.webp"/>
<<elseif $PH is 7>>
<img src="assets/img/ph/soft/8.webp"/>
<</if>><<set $Excitement++>><<if $Excitement >= 10>><<InformationUiPopUp "You just climaxed">>
<<if $Stress <= $StressMin>><em>Stress already at minimum</em><<elseif $Stress > $StressMin>><em>-5 stress</em><<set $Stress -= 5>><</if>><<set $Energy-->><<set $Excitement = 0>>
<</InformationUiPopUp>><</if>>
<div class="BottomUiBarCustom">
<<BottomButton "Action">>[[🔄 Again|PornSoft]]<</BottomButton>>
<<BottomButton "Move">><<return [[↩️ Back|Porn]]>><</BottomButton>>
</div><<sound "music" "music.music" true>><<passagebg>><<set $PH to random(7)>><<if $PH is 0>>
<img src="assets/img/ph/anal/1.webp"/>
<<elseif $PH is 1>>
<img src="assets/img/ph/anal/2.webp"/>
<<elseif $PH is 2>>
<img src="assets/img/ph/anal/3.webp"/>
<<elseif $PH is 3>>
<img src="assets/img/ph/anal/4.webp"/>
<<elseif $PH is 4>>
<img src="assets/img/ph/anal/5.webp"/>
<<elseif $PH is 5>>
<img src="assets/img/ph/anal/6.webp"/>
<<elseif $PH is 6>>
<img src="assets/img/ph/anal/7.webp"/>
<<elseif $PH is 7>>
<img src="assets/img/ph/anal/8.webp"/>
<</if>><</passagebg>><<if $PH is 0>>
<img src="assets/img/ph/anal/1.webp"/>
<<elseif $PH is 1>>
<img src="assets/img/ph/anal/2.webp"/>
<<elseif $PH is 2>>
<img src="assets/img/ph/anal/3.webp"/>
<<elseif $PH is 3>>
<img src="assets/img/ph/anal/4.webp"/>
<<elseif $PH is 4>>
<img src="assets/img/ph/anal/5.webp"/>
<<elseif $PH is 5>>
<img src="assets/img/ph/anal/6.webp"/>
<<elseif $PH is 6>>
<img src="assets/img/ph/anal/7.webp"/>
<<elseif $PH is 7>>
<img src="assets/img/ph/anal/8.webp"/>
<</if>><<set $Excitement++>><<if $Excitement >= 10>><<InformationUiPopUp "You just climaxed">>
<<if $Stress <= $StressMin>><em>Stress already at minimum</em><<elseif $Stress > $StressMin>><em>-5 stress</em><<set $Stress -= 5>><</if>><<set $Energy-->><<set $Excitement = 0>>
<</InformationUiPopUp>><</if>>
<div class="BottomUiBarCustom">
<<BottomButton "Action">>[[🔄 Again|PornAnal]]<</BottomButton>>
<<BottomButton "Move">><<return [[↩️ Back|Porn]]>><</BottomButton>>
</div><<sound "music" "music.music" true>><<passagebg>><<set $PH to random(7)>><<if $PH is 0>>
<img src="assets/img/ph/hardcore/1.webp"/>
<<elseif $PH is 1>>
<img src="assets/img/ph/hardcore/2.webp"/>
<<elseif $PH is 2>>
<img src="assets/img/ph/hardcore/3.webp"/>
<<elseif $PH is 3>>
<img src="assets/img/ph/hardcore/4.webp"/>
<<elseif $PH is 4>>
<img src="assets/img/ph/hardcore/5.webp"/>
<<elseif $PH is 5>>
<img src="assets/img/ph/hardcore/6.webp"/>
<<elseif $PH is 6>>
<img src="assets/img/ph/hardcore/7.webp"/>
<<elseif $PH is 7>>
<img src="assets/img/ph/hardcore/8.webp"/>
<</if>><</passagebg>><<if $PH is 0>>
<img src="assets/img/ph/hardcore/1.webp"/>
<<elseif $PH is 1>>
<img src="assets/img/ph/hardcore/2.webp"/>
<<elseif $PH is 2>>
<img src="assets/img/ph/hardcore/3.webp"/>
<<elseif $PH is 3>>
<img src="assets/img/ph/hardcore/4.webp"/>
<<elseif $PH is 4>>
<img src="assets/img/ph/hardcore/5.webp"/>
<<elseif $PH is 5>>
<img src="assets/img/ph/hardcore/6.webp"/>
<<elseif $PH is 6>>
<img src="assets/img/ph/hardcore/7.webp"/>
<<elseif $PH is 7>>
<img src="assets/img/ph/hardcore/8.webp"/>
<</if>><<set $Excitement++>><<if $Excitement >= 10>><<InformationUiPopUp "You just climaxed">>
<<if $Stress <= $StressMin>><em>Stress already at minimum</em><<elseif $Stress > $StressMin>><em>-5 stress</em><<set $Stress -= 5>><</if>><<set $Energy-->><<set $Excitement = 0>>
<</InformationUiPopUp>><</if>>
<div class="BottomUiBarCustom">
<<BottomButton "Action">>[[🔄 Again|PornHardcore]]<</BottomButton>>
<<BottomButton "Move">><<return [[↩️ Back|Porn]]>><</BottomButton>>
</div><<sound "music" "music.music" true>><<passagebg>><img src="assets/img/misc/MCPC/play/cs2.webp"/><</passagebg>><<InformationUiPopUp "Quick CS2 session">>
<<if $Stress <= $StressMin>><em>Stress already at minimum</em><<elseif $Stress > $StressMin>><em>-10 stress</em><<set $Stress -= 10>><</if>>
<</InformationUiPopUp>>
<div class="BottomUiBarCustom">
<<BottomButton "Move">><<link "↩️ Return">><<set $Time++>><<set $Energy-->><<goto "Play">><</link>><</BottomButton>>
</div><<sound "music" "music.music" true>><<passagebg>><img src="assets/img/misc/MCPC/play/minecraft.webp"/><</passagebg>><<InformationUiPopUp "Quick Minecraft session like the old days!">>
<<if $Stress <= $StressMin>><em>Stress already at minimum</em><<elseif $Stress > $StressMin>><em>-10 stress</em><<set $Stress -= 10>><</if>>
<</InformationUiPopUp>>
<div class="BottomUiBarCustom">
<<BottomButton "Move">><<link "↩️ Return">><<set $Time++>><<set $Energy-->><<goto "Play">><</link>><</BottomButton>>
</div><<sound "music" "music.music" true>><<sound "bg" "bg.empty" true>><<passagebg>><<if $Time !== 3>><img src="assets/img/misc/home/housematefemalebedroom.webp"/><<else>><img src="assets/img/misc/home/housematefemalebedroomnight.webp"/><</if>><</passagebg>>
<<if $Time == 3>><<Interact $NPCHousemateFemale>><<else>><<InformationUiPopUp "Interact">>There is no one.<</InformationUiPopUp>><</if>>
<div class="BottomUiBarCustom"><<if $Inventory.spycam and $Spycam.housematefemale == false>><br><<BottomButton "Action">><<link "📷 Place Spycam">><<set $Spycam.housematefemale = true>><<set $Inventory.spycam.qty -= 1>><<if $Inventory.spycam.qty <= 0>><<run delete State.variables.Inventory.spycam>><</if>><<Refresh>><</link>><</BottomButton>><</if>>
<<BottomButton "Move">>[[🚪 Leave the bedroom|HomeCorridor]]<</BottomButton>>
</div><<sound "music" "music.music" true>><<sound "bg" "bg.empty" true>><<passagebg>><img src="assets/img/misc/home/bathroom/bathroom.webp"/><</passagebg>>
<div class="BottomUiBarCustom">
<<BottomButton "Action">><<if $Inventory.spycam and $Spycam.bathroom == false>><<link "📷 Place Spycam">><<set $Spycam.bathroom = true>><<set $Inventory.spycam.qty -= 1>><<if $Inventory.spycam.qty <= 0>><<run delete State.variables.Inventory.spycam>><</if>><<Refresh>><</link>><</if>>
<<if $Time == 0>><<if ($NPCHousemateFemale.lvl == 0 and $NPCHousemateFemale.talklvl == 0 and $PsychicPower >= 1) or ($NPCHousemateFemale.lvl == 4 and $NPCHousemateFemale.talklvl == 4 and $PsychicPower >= 1)>><<link "🚿 <<=$NPCHousemateFemale.name>> Taking Shower">><<set $FromOtherPlace = true>><<SetReturnTo>><<set $ActiveNPC = $NPCHousemateFemale>><<goto "Talk.HousemateFemale">><</link>><<elseif ($PsychicPower <= 0 and $NPCHousemateFemale.lvl == 0) or ($PsychicPower <= 0 and $NPCHousemateFemale.lvl == 4)>><<link "🔒 Not enough Psychic Power">><</link>><<else>><<link "🚿 <<=$NPCHousemateFemale.name>> Taking Shower">><<goto "PeekHousemateFemale">><</link>><</if>><<elseif $Time == 2>><<link "🚿 <<=$NPCLandlady.name>> Taking Shower">><<goto "PeekLandlady">><</link>><</if>><<else>><<if $ShowerDayTime == false>>[[🚿 Take a shower|Shower]]<<elseif $ShowerDayTime == true>><<link "🚿 Already Taken Shower Today">><</link>><</if>><</if>><</BottomButton>>
<<BottomButton "Move">>[[🚪 Leave the bathroom|HomeCorridor]]<</BottomButton>>
</div><<sound "music" "music.music" true>><<sound "bg" "bg.empty" true>><<passagebg>><<if $Time !== 3>><img src="assets/img/misc/home/housematemalebedroom.webp"/><<else>><img src="assets/img/misc/home/housematemalebedroomnight.webp"/><</if>><</passagebg>>
<<if $Time == 3 or 0>><<Interact $NPCHousemateMale>><<else>><<InformationUiPopUp "Interact">>There is no one.<</InformationUiPopUp>><</if>>
<div class="BottomUiBarCustom"><<if $Inventory.spycam and $Spycam.housematemale == false>><br><<BottomButton "Action">><<link "📷 Place Spycam">><<set $Spycam.housematemale = true>><<set $Inventory.spycam.qty -= 1>><<if $Inventory.spycam.qty <= 0>><<run delete State.variables.Inventory.spycam>><</if>><<Refresh>><</link>><</BottomButton>><</if>>
<<BottomButton "Move">>[[🚪 Leave the bedroom|HomeCorridor]]<</BottomButton>>
</div><<sound "music" "music.music" true>><<sound "bg" "bg.empty" true>><<passagebg>><<if $Time !== 3>><img src="assets/img/misc/home/mainbedroom.webp"/><<else>><img src="assets/img/misc/home/mainbedroomnight.webp"/><</if>><</passagebg>>
<<if $Time == 0>><<Interact $NPCLandlady>>
<<Interact $NPCLandlord>><<elseif $Time == 3>><<Interact $NPCLandlady>><<else>><<InformationUiPopUp "Interact">>There is no one.<</InformationUiPopUp>><</if>><<if $NPCLandlady.lvl == 5 and $Time == 3 and $NPCLandlady.lastCorruptBool == false and $NPCLandlordSleepDrug == true>><<set $FromOtherPlace = true>><<set $ReturnTo = "MainBedroom">><<set $ActiveNPC = $NPCLandlady>><<goto "Talk.Landlady">><</if>>
<div class="BottomUiBarCustom"><<if $Inventory.spycam and $Spycam.mainbedroom == false>><br><<BottomButton "Action">><<link "📷 Place Spycam">><<set $Spycam.mainbedroom = true>><<set $Inventory.spycam.qty -= 1>><<if $Inventory.spycam.qty <= 0>><<run delete State.variables.Inventory.spycam>><</if>><<Refresh>><</link>><</BottomButton>><</if>>
<<BottomButton "Move">>[[🚪 Leave the bedroom|HomeCorridor]]<</BottomButton>>
</div><<sound "music" "music.music" true>><<sound "bg" "bg.empty" true>><<passagebg>><<if $Time !== 3>><img src="assets/img/misc/home/entrance.webp"/><<else>><img src="assets/img/misc/home/entrancenight.webp"/><</if>><</passagebg>><<if $NPCLandlady.lvl == 2 and $Time == 1 and $NPCLandladyCorruptionTalklvl2 == true>><<set $FromOtherPlace = true>><<set $ReturnTo = "HomeLivingRoom">><<set $ActiveNPC = $NPCLandlady>><<goto "Talk.Landlady">><</if>><<if $SedativesDeliveredWaiting == true and $LandladyChapter6Story2Played == false>><<goto "LandladyChapter6Story2">><</if>>
<div class="BottomUiBarCustom">
<<BottomButton "Move">>[[⬆️ Go upstairs|HomeCorridor]]
[[📺 Living room|HomeLivingRoom]]
[[🍴 Kitchen|HomeKitchen]]
[[🌳 Garden|HomeGarden]]
<<link "🚪 Go out into the neighborhood">><<set $InteractInInterior = false>><<goto "Neighborhood">><</link>><</BottomButton>>
</div><<sound "music" "music.music" true>><<sound "sfx" "sfx.shower" true>><<passagebg>><img src="assets/img/misc/home/bathroom/shower.webp"/><</passagebg>><<InformationUiPopUp "Shower">>
<<if $Energy < $EnergyMax>><em>+1 energy</em><<set $Energy += 1>><<elseif $Energy >= $EnergyMax>><em>Energy already at maximum</em><</if>>
<<if $Stress <= $StressMin>><em>Stress already at minimum</em><<elseif $Stress > $StressMin>><em>-5 stress</em><<set $Stress -= 5>><</if>>
<</InformationUiPopUp>>
<div class="BottomUiBarCustom">
<<BottomButton "Move">>[[Return|Bathroom]]<<set $ShowerDayTime = true>><</BottomButton>>
</div><<sound "music" "music.music" true>><<passagebg>><<if $Time !== 3>><<sound "bg" "bg.neighborhood" true>><img src="assets/img/misc/neighborhood/neighborhood.webp"/><<else>><<sound "bg" "bg.neighborhoodNight" true>><img src="assets/img/misc/neighborhood/neighborhoodnight.webp"/><</if>><</passagebg>>
<<imgcorruption park>>
<div class="BottomUiBarCustom">
<<BottomButton "Move">><<link "🏠 Home entrance">><<set $InteractInInterior = true>><<goto "HomeEntrance">><</link>>
[[🏡 Left neighbor|LeftNeighbor]]
[[🏡 Right neighbor|RightNeighbor]]<<if $NPCPrincipalHouseAccess == true>>
<<link "🏡 Principal Home">><<set $InteractInInterior = true>><<goto "PrincipalHome">><</link>><<else>>
<<link "🔒 Principal Home">><</link>><</if>><<if $NPCMayorHouseAccess == true>>
<<link "🏡 Mayor Home">><<set $InteractInInterior = true>><<goto "MayorHome">><</link>><<else>>
<<link "🔒 Mayor Home">><</link>><</if>>
<<link "🏙️ City center">><<set $TravelPerTime++>><<goto "City">><</link>><</BottomButton>>
</div><<sound "music" "music.music" true>><<sound "bg" "bg.empty" true>><<passagebg>><<if $Time !== 3>><img src="assets/img/misc/home/livingroom.webp"/><<else>><img src="assets/img/misc/home/livingroomnight.webp"/><</if>><</passagebg>>
<<if $Time == 3>><<if $NPCLandlordSleepDrug == true>><<InformationUiPopUp "Interact">><<print $NPCLandlord.name>> is sleeping...<</InformationUiPopUp>><<else>><<Interact $NPCLandlord>><</if>><<else>><<InformationUiPopUp "Interact">>There is no one.<</InformationUiPopUp>><</if>><<if $NPCLandlady.lvl == 1 and $Time == 1 and $NPCLandladyCorruptionTalklvl1 == true>><<set $FromOtherPlace = true>><<set $ReturnTo = "HomeLivingRoom">><<set $ActiveNPC = $NPCLandlady>><<goto "Talk.Landlady">><</if>><<if $NPCLandlady.lvl == 3 and $Time == 1 and $NPCLandladyCorruptionTalklvl3 == true>><<set $FromOtherPlace = true>><<set $ReturnTo = "HomeLivingRoom">><<set $ActiveNPC = $NPCLandlady>><<goto "Talk.Landlady">><</if>><<if $NPCLandlady.lvl == 4 and $Time == 2 and $NPCLandladyChapter5 == true and $PsychicPower >= 1 and $NPCLandlady.lastCorruptBool == false>><<set $FromOtherPlace = true>><<set $ReturnTo = "Bathroom">><<set $ActiveNPC = $NPCLandlady>><<goto "Talk.Landlady">><</if>>
<div class="BottomUiBarCustom">
<<BottomButton "Action">>[[📺 Watch TV|ViewTV]]<</BottomButton>>
<<BottomButton "Move">>[[🚪 Leave the living room|HomeEntrance]]<</BottomButton>>
</div><<sound "music" "music.music" true>><<sound "bg" "bg.empty" true>><<passagebg>><<if $Time !== 3>><img src="assets/img/misc/home/kitchen.webp"/><<else>><img src="assets/img/misc/home/kitchennight.webp"/><</if>><</passagebg>>
<<if $NPCLandlady.lvl == 1 and $Time == 1 and $NPCLandladyCorruptionTalklvl1 == true>><<set $FromOtherPlace = true>><<InformationUiPopUp "Interact">>There is no one.<</InformationUiPopUp>><<elseif $NPCLandlady.lvl == 2 and $Time == 1 and $NPCLandladyCorruptionTalklvl2 == true>><<InformationUiPopUp "Interact">>There is no one.<</InformationUiPopUp>><<elseif $NPCLandlady.lvl == 3 and $Time == 1 and $NPCLandladyCorruptionTalklvl3 == true>><<InformationUiPopUp "Interact">>There is no one.<</InformationUiPopUp>><<elseif $Time == 1>><<Interact $NPCLandlady>><<else>><<InformationUiPopUp "Interact">>There is no one.<</InformationUiPopUp>><</if>>
<div class="BottomUiBarCustom"><<if $SedativesDelivered == true and $LandladyChapter6Story3Played == false and $Time == 3>><br><<BottomButton "Action">><<link "💊 Use sedatives">><<goto "LandladyChapter6Story3">><</link>><</BottomButton>><</if>>
<<BottomButton "Move">>[[🚪 Leave the kitchen|HomeEntrance]]<</BottomButton>>
</div><<sound "music" "music.music" true>><<passagebg>><<if $Time !== 3>><<sound "bg" "bg.neighborhood" true>><img src="assets/img/misc/home/garden.webp"/><<else>><<sound "bg" "bg.neighborhoodNight" true>><img src="assets/img/misc/home/gardennight.webp"/><</if>><</passagebg>>
<<if $Time == 2>><<Interact $NPCHousemateFemale>><<else>><<InformationUiPopUp "Interact">>There is no one.<</InformationUiPopUp>><</if>>
<div class="BottomUiBarCustom">
<<BottomButton "Move">>[[🏠 Go back into the house|HomeEntrance]]<</BottomButton>>
</div><<sound "music" "music.music" true>><<passagebg>><<if $Time !== 3>><<sound "bg" "bg.neighborhood" true>><img src="assets/img/misc/neighborhood/rightneighbor.webp"/><<else>><<sound "bg" "bg.neighborhoodNight" true>><img src="assets/img/misc/neighborhood/rightneighbornight.webp"/><</if>><</passagebg>>
<div class="BottomUiBarCustom">
<<BottomButton "Action">><<if $NPCRightNeighbor.home == true>>[[➡️ Enter|RHNHome]]<<elseif $NPCRightNeighbor.athome == true>>[[✊ Knock|RHNHome]]<<elseif $NPCRightNeighbor.athome == false>><<link "✊ Knock">><<goto "DoorClosed">><</link>><</if>><</BottomButton>>
<<BottomButton "Move">>[[🏘️ Neighborhood|Neighborhood]]<</BottomButton>>
</div><<sound "music" "music.music" true>><<passagebg>><<if $Time !== 3>><<sound "bg" "bg.neighborhood" true>><img src="assets/img/misc/neighborhood/leftneighbor.webp"/><<else>><<sound "bg" "bg.neighborhoodNight" true>><img src="assets/img/misc/neighborhood/leftneighbornight.webp"/><</if>><</passagebg>>
<div class="BottomUiBarCustom">
<<BottomButton "Action">><<if $NPCLeftNeighbor.home == true>>[[➡️ Enter|LHNHome]]<<elseif $NPCLeftNeighbor.athome == true>>[[✊ Knock|LHNHome]]<<elseif $NPCLeftNeighbor.athome == false>><<link "✊ Knock">><<goto "DoorClosed">><</link>><</if>><</BottomButton>>
<<BottomButton "Move">>[[🏘️ Neighborhood|Neighborhood]]<</BottomButton>>
</div><<sound "music" "music.music" true>><<passagebg>><<if $Time !== 3>><<sound "bg" "bg.city" true>><img src="assets/img/misc/city/city.webp"/><<else>><<sound "bg" "bg.cityNight" true>><img src="assets/img/misc/city/citynight.webp"/><</if>><</passagebg>><<if $Time == 1 or $Time == 2>><<if $MayorStoryEncounter1 == true and $MayorStoryEncounter1Goto == false>><<goto "MayorStory9">><<set $MayorStoryEncounter1Goto = true>><</if>><</if>><<if $Time !== 3>><<if $MayorStoryEncounter2 == true and $MayorStoryEncounter2Goto == false>><<goto "MayorStory10">><<set $MayorStoryEncounter2Goto = true>><</if>><</if>>
<<if $Time == 2>><<Interact $NPCHomeless>><<else>><<InformationUiPopUp "Interact">>There is no one.<</InformationUiPopUp>><</if>>
<<imgcorruption city>>
<div class="BottomUiBarCustom">
<<BottomButton "Move">>[[🌲 Park|Park]]
[[🏛️ City Hall|CityHall]]
[[🏟️ Arena|Arena]]
[[🛍️ Mall|Mall]]
[[🏢 Apartments|ApartmentsOutside]]
<<link "🏫 University">><<goto "University">><<set $TravelPerTime++>><</link>>
<<link "🏬 Financial district">><<goto "FinancialQuarter">><<set $TravelPerTime++>><</link>>
<<link "🏚️ Old town">><<goto "Oldtown">><<set $TravelPerTime++>><</link>>
<<link "👮 Police">><<goto "Police">><<set $TravelPerTime++>><</link>>
<<link "🏥 Hospital">><<goto "Hospital">><<set $TravelPerTime++>><</link>>
<<link "🏘️ My neighborhood">><<goto "Neighborhood">><<set $TravelPerTime++>><</link>><<if $PlayerHasCar == true>>
<<link "🏞️ Countryside">><<goto "Countryside">><<set $TravelPerTime++>><</link>><<else>>
<<link "🔒 Countryside">><</link>><</if>><</BottomButton>>
</div><<sound "music" "music.music" true>><<passagebg>><<if $Time !== 3>><<sound "bg" "bg.city" true>><img src="assets/img/misc/oldtown/oldtown.webp"/><<else>><<sound "bg" "bg.cityNight" true>><img src="assets/img/misc/oldtown/oldtownnight.webp"/><</if>><</passagebg>>
<<if $Time !== 2>><<Interact $NPCHomeless>><<else>><<InformationUiPopUp "Interact">>There is no one.<</InformationUiPopUp>><</if>>
<<imgcorruption city>>
<div class="BottomUiBarCustom"><<if $TalkDealer3 == true>><br><<BottomButton "Deal">><<DrugSell 1 15 40>><</BottomButton>><</if>>
<<BottomButton "Move">>[[🏚️ Trap House|TrapHouse]]<<if $TalkDealer1 == true>><br>[[🥊 The Pit|DoorThePit]]<</if>>
[[👠 Red Light District|RedLightDistrict]]
<<link "🏙️ City center">><<goto "City">><<set $TravelPerTime++>><</link>><</BottomButton>>
</div><<sound "music" "music.music" true>><<passagebg>><<if $Time !== 3>><<sound "bg" "bg.park" true>><img src="assets/img/misc/city/park/park.webp"/><<else>><<sound "bg" "bg.parkNight" true>><img src="assets/img/misc/city/park/parknight.webp"/><</if>><</passagebg>>
<<imgcorruption park>>
<div class="BottomUiBarCustom"><<if $TalkDealer3 == true>><br><<BottomButton "Deal">><<DrugSell 2 40 20>><</BottomButton>><</if>>
<<BottomButton "Action">><<if $FitnessDayTime == false>>[[🏃 Run|Jogging]]<<elseif $FitnessDayTime is true>><<link "😩 Already Exercised Today">><</link>><</if>><</BottomButton>>
<<BottomButton "Move">>[[🚻 Toilet|ParkToilet]]
[[🏙️ City center|City]]<</BottomButton>>
</div><<sound "music" "music.music" true>><<passagebg>><<if $Time !== 3>><<sound "bg" "bg.university" true>><img src="assets/img/misc/university/university.webp"/><<else>><<sound "bg" "bg.universityNight" true>><img src="assets/img/misc/university/universitynight.webp"/><</if>><</passagebg>>
<<if $Time == 0>><<Interact $NPCMate1>><<elseif $Time == 1>><<Interact $NPCMate2>><<elseif $Time == 2>><<Interact $NPCMate3>><<else>><<InformationUiPopUp "Interact">>There is no one.<</InformationUiPopUp>><</if>>
<<imgcorruption city>>
<div class="BottomUiBarCustom"><<if $TalkDealer3 == true>><br><<BottomButton "Deal">><<DrugSell 2 40 20>><</BottomButton>><</if>>
<<BottomButton "Move">><<if $Time !== 3 or $Key.college == true>>[[📚 Classroom 1|UniversityClass1]]
[[📚 Classroom 2|UniversityClass2]]
[[🏋 Gymnasium|UniversityGymnasium]]
<<if $PlayerWorkUniversity == true>>[[🛋️ Teachers lounge|UniversityStaffRoom]]<<else>><<link "🔒 Teachers lounge">><</link>><</if>>
[[🖥️ Principal's office|UniversityPrincipalOffice]]
[[🚻 Toilet|UniversityToilet]]<<else>><<link "🔒 University is closed">><</link>><</if>>
<<link "🏙️ City center">><<goto "City">><<set $TravelPerTime++>><</link>><</BottomButton>>
</div><<sound "music" "music.music" true>><<passagebg>><<if $Time !== 3>><<sound "bg" "bg.city" true>><img src="assets/img/misc/oldtown/redlight/redlight.webp"/><<else>><<sound "bg" "bg.cityNight" true>><img src="assets/img/misc/oldtown/redlight/redlightnight.webp"/><</if>><</passagebg>>
<<imgcorruption city>>
<div class="BottomUiBarCustom">
<<BottomButton "Move">><<if $Time == 0>><<link "🔒 Sexshop is closed">><</link>><<else>>[[🫦 Sexshop|Sexshop]]<</if>>
<<if $Time == 0>><<link "🔒 Stripclub is closed">><</link>><<else>>[[🔞 Stripclub|Stripclub]]<</if>>
[[🎰 Casino|Casino]]
[[🏚️ Old district|Oldtown]]<</BottomButton>>
</div><<sound "music" "music.music" true>><<passagebg>><<if $Time !== 3>><<sound "bg" "bg.city" true>><img src="assets/img/misc/city/cityhall/cityhall.webp"/><<else>><<sound "bg" "bg.cityNight" true>><img src="assets/img/misc/city/cityhall/cityhallnight.webp"/><</if>><</passagebg>>
<<imgcorruption city>>
<div class="BottomUiBarCustom"><<if $Time == 0 and $MayorStoryInfo1 == false and $Fitness >= 25>><<BottomButton "Decision">><<link "👀 Move closer">><<goto "MayorStory1">><</link>><</BottomButton>><</if>><<if $Time == 3 and $MayorStoryInfo2 == true and $MayorStoryInfo3 == false>><<BottomButton "Decision">><<if $OptSkipMiniGamesOn == false>><<link "🕵️ Sneak in">><<goto "MayorStory3">><</link>><<else>><<link "🕵️ Sneak in">><<goto "MayorStory4">><</link>><</if>><</BottomButton>><</if>>
<<BottomButton "Move">><<if $Time !== 3 or $Key.cityhall == true>>[[🖥️ Mayor's Office|CHMayorOffice]]
[[🗳️ Meeting room|CHMeetingRoom]]<<else>><<link "🔒 City hall is closed">><</link>><</if>>
[[🏙️ City center|City]]<</BottomButton>>
</div><<sound "music" "music.music" true>><<passagebg>><<if $Time !== 3>><<sound "bg" "bg.mall" true>><img src="assets/img/misc/city/mall/mall.webp"/><<else>><<sound "bg" "bg.empty" true>><img src="assets/img/misc/city/mall/mallnight.webp"/><</if>><</passagebg>>
<<imgcorruption mall>>
<div class="BottomUiBarCustom">
<<BottomButton "Move">><<if $Time == 3>><<link "🔒 Mall is closed">><</link>><<else>>[[🧥 Clothing store|ClothingStore]]
[[💻 Electronics store|ElectronicStore]]
[[🛒 Supermarket|Supermarket]]
[[🚗 Car dealer|CarDealer]]
[[💪 Gym|Gym]]<</if>>
[[🏙️ City center|City]]<</BottomButton>>
</div><<sound "music" "music.music" true>><<passagebg>><<if $Time !== 3>><<sound "bg" "bg.city" true>><img src="assets/img/misc/financialquarter/financialquarter.webp"/><<else>><<sound "bg" "bg.cityNight" true>><img src="assets/img/misc/financialquarter/financialquarternight.webp"/><</if>><</passagebg>>
<<imgcorruption city>>
<div class="BottomUiBarCustom"><<if $TalkDealer3 == true>><br><<BottomButton "Deal">><<DrugSell 3 60 10>><</BottomButton>><</if>>
<<BottomButton "Move">><<if $Time == 3>><<link "🔒 Bank is closed">><</link>><<else>>[[🏦 Bank|Bank]]<</if>><<if $MayorStoryInfo14 == true>><br>[[🏢 Building|Building]]<</if>>
<<link "🏙️ City center">><<goto "City">><<set $TravelPerTime++>><</link>><</BottomButton>>
</div><<if _pmOpen>><div class="pm2-root"><div class="pm2-panel"><div class="pm2-logo"><img class="pm2-logo-img" src="assets/logo.png" alt="Logo"></div><div class="pm2-actions"><button class="pm2-btn" data-act="return">Resume</button>
<button class="pm2-btn" data-act="save">Save / Load</button>
<button class="pm2-btn" data-wiki="<<CheatMenu>>">Cheat</button>
<button class="pm2-btn" data-act="restart">Main Menu</button>
<<if setup.isNW()>><button class="pm2-btn pm2-danger" data-act="quit">Quit Game</button><br><</if>>
<div class="pm2-icons">
<button class="pm2-icon" data-act="options" aria-label="Settings" title="Settings">⚙️</button>
<button class="pm2-icon" data-wiki="<<SupportMenu>>" aria-label="Support Game" title="Support Game">🛟</button>
<button class="pm2-icon" style="position:relative;" data-wiki="<<AchievementsMenu>>" aria-label="Achievements" title="Achievements">🏆<span id="pm2AchDot" style="position:absolute;top:-4px;right:-4px;width:10px;height:10px;border-radius:999px;background:#e65763;border:1.5px solid rgba(8,8,8,.9);display:none;box-shadow:0 0 8px rgba(230,87,99,.7);"></span></button>
</div></div><div class="pm2-version"><<print $GameVersion.name>></div></div></div><style>
html.pause-open #ui-dialog-titlebar,
html.pause-open #ui-dialog-close { display: none !important; }
html.pause-open #ui-dialog.pauseMenuDialog {
position: fixed !important;
inset: 0 !important;
width: 100vw !important;
height: 100vh !important;
max-width: 100vw !important;
max-height: 100vh !important;
transform: none !important;
margin: 0 !important;
background: transparent !important;
overflow: hidden !important;
border: 0 !important;
border-radius: 0;
box-shadow: none !important;
}
html.pause-open #ui-dialog.pauseMenuDialog #ui-dialog-body {
position: relative !important;
z-index: 1 !important;
padding: 0 !important;
margin: 0 !important;
width: 100% !important;
height: 100% !important;
background: transparent !important;
border-radius: 0;
overflow: hidden !important;
}
html.pause-open .pm2-confirm-backdrop {
position: absolute !important;
inset: 0 !important;
z-index: 999 !important;
display: flex !important;
align-items: center !important;
justify-content: center !important;
background: rgba(0,0,0,.55) !important;
backdrop-filter: blur(2px) !important;
-webkit-backdrop-filter: blur(2px) !important;
}
html.pause-open .pm2-confirm {
width: min(520px, calc(100vw - 32px)) !important;
border: 1px solid rgba(255,255,255,.14) !important;
background: rgba(18,18,20,.92) !important;
border-radius: 14px !important;
box-shadow: 0 20px 60px rgba(0,0,0,.65) !important;
padding: 16px 16px 14px 16px !important;
box-sizing: border-box !important;
}
html.pause-open .pm2-confirm-title {
font-weight: 750 !important;
letter-spacing: .2px !important;
color: rgba(255,255,255,.92) !important;
margin: 0 0 8px 0 !important;
text-shadow: 0 1px 10px rgba(0,0,0,.55) !important;
}
html.pause-open .pm2-confirm-msg {
color: rgba(255,255,255,.86) !important;
line-height: 1.35 !important;
margin: 0 0 14px 0 !important;
}
html.pause-open .pm2-confirm-actions {
display: flex !important;
gap: 10px !important;
justify-content: flex-end !important;
align-items: center !important;
flex-wrap: wrap !important;
}
html.pause-open .pm2-confirm-actions .pm2-btn {
min-width: 140px !important;
}
html.pause-open .pm2-root {
position: relative !important;
width: 100% !important;
height: 100% !important;
background: transparent !important;
text-align: left !important;
}
html.pause-open .pm2-root::before {
content: "" !important;
position: absolute !important;
inset: 0 !important;
background: linear-gradient(90deg,
rgba(8,8,8,1) 0%,
rgba(8,8,8,1) 25%,
rgba(8,8,8,0) 100%
) !important;
z-index: 1 !important;
pointer-events: none !important;
}
html.pause-open .pm2-root::after {
content: "" !important;
position: absolute !important;
top: 0 !important;
left: 0 !important;
bottom: 0 !important;
width: 100% !important;
background-image: url("assets/background.gif") !important;
background-size: cover !important;
background-position: center !important;
background-repeat: no-repeat !important;
opacity: 0.12 !important;
mask-image: linear-gradient(90deg, rgba(0,0,0,1) 0%, rgba(8,8,8,0) 35%) !important;
-webkit-mask-image: linear-gradient(90deg, rgba(8,8,8,1) 0%, rgba(8,8,8,0) 35%) !important;
z-index: 2 !important;
pointer-events: none !important;
}
html.pause-open .pm2-panel {
--pm2-col: clamp(200px, 25vw, 280px);
--pm2-pad-left: clamp(18px, 8vw, 100px);
position: relative !important;
z-index: 10 !important;
height: 100% !important;
width: calc(var(--pm2-col) + var(--pm2-pad-left)) !important;
max-width: 90vw !important;
padding: 0 18px 0 var(--pm2-pad-left) !important;
display: flex !important;
flex-direction: column !important;
align-items: flex-start !important;
justify-content: space-between !important;
box-sizing: border-box !important;
}
html.pause-open .pm2-logo {
width: var(--pm2-col) !important;
max-width: var(--pm2-col) !important;
display: flex !important;
justify-content: center !important;
align-items: flex-end !important;
flex: 1 1 auto !important;
padding: 0 !important;
margin: 0 !important;
box-sizing: border-box !important;
}
html.pause-open .pm2-logo-img {
display: block !important;
width: auto !important;
max-width: 100% !important;
min-width: 0 !important;
max-height: clamp(80px, 25vh, 200px) !important;
min-height: 0 !important;
height: auto !important;
object-fit: contain !important;
object-position: center !important;
margin: 0 !important;
padding: 0 !important;
border: 0 !important;
vertical-align: top !important;
user-select: none !important;
-webkit-user-drag: none !important;
filter: drop-shadow(0 10px 26px rgba(0,0,0,.55)) !important;
}
html.pause-open .pm2-actions {
width: var(--pm2-col) !important;
max-width: var(--pm2-col) !important;
display: flex !important;
flex-direction: column !important;
gap: 0 !important;
flex: 0 0 auto !important;
margin: clamp(16px,3vh,32px) 0 !important;
padding: 0 !important;
box-sizing: border-box !important;
}
html.pause-open .pm2-btn {
appearance: none !important;
-webkit-appearance: none !important;
display: block !important;
width: 100% !important;
max-width: 100% !important;
margin: 0 !important;
align-self: flex-start !important;
padding: clamp(8px,1.2vh,12px) 14px !important;
border: 1px solid rgba(255,255,255,.14) !important;
background: rgba(18,18,20,.82) !important;
color: #f4f4f6 !important;
font-size: calc(clamp(12px,1.4vw,15px) + var(--font-boost,0px)) !important;
font-weight: 650 !important;
letter-spacing: .2px !important;
cursor: pointer !important;
text-align: center !important;
border-radius: 3px !important;
box-sizing: border-box !important;
}
html.pause-open .pm2-btn:hover { filter: brightness(1.08) !important; }
html.pause-open .pm2-danger {
border-color: rgba(255,90,90,.32) !important;
background: rgba(35,16,16,.78) !important;
}
html.pause-open .pm2-icons {
display: flex !important;
gap: clamp(8px,1.5vw,16px) !important;
align-items: center !important;
justify-content: center !important;
width: 100% !important;
margin: clamp(8px,1.5vh,16px) 0 0 0 !important;
padding: 0 !important;
}
html.pause-open .pm2-icon {
appearance: none !important;
-webkit-appearance: none !important;
flex: 1 1 0 !important;
height: clamp(36px, 10vh, 50px) !important;
max-width: clamp(36px, 10vh, 50px) !important;
margin: 0 !important;
padding: 0 !important;
border: 1px solid rgba(255, 255, 255, .14) !important;
background: rgba(18, 18, 20, .70) !important;
color: #fff !important;
font-size: clamp(16px, 2.2vw, 20px) !important;
cursor: pointer !important;
display: inline-flex !important;
align-items: center !important;
justify-content: center !important;
border-radius: 5px !important;
box-sizing: border-box !important;
position: relative !important;
}
html.pause-open .pm2-icon:hover { filter: brightness(1.10) !important; }
html.pause-open .pm2-version {
width: var(--pm2-col) !important;
flex: 1 1 auto !important;
display: flex !important;
align-items: center !important;
justify-content: center !important;
text-align: center !important;
font-size: calc(clamp(10px,1.2vw,12px) + var(--font-boost,0px)) !important;
opacity: .85 !important;
color: rgba(255,255,255,.82) !important;
text-shadow: 0 1px 10px rgba(0,0,0,.55) !important;
margin: 0 !important;
padding: 0 !important;
box-sizing: border-box !important;
}
@media (max-width: 520px) {
html.pause-open .pm2-panel {
--pm2-col: min(250px, 70vw);
--pm2-pad-left: 18px;
}
html.pause-open .pm2-logo-img { max-height: 80px !important; }
html.pause-open .pm2-root::after { width: 74% !important; }
}
</style><<script>>
(function(){
function hasUnclaimedAchReward(){
try{
var V=State.variables;
if(V.CheatOn===true) return false;
var data=Array.isArray(V.Achievements)?V.Achievements:setup.AchievementsData();
for(var i=0;i<data.length;i++){
var a=data[i];
if(!a.reward||!a.reward.enabled) continue;
if(V["_AchRewarded_"+a.id]) continue;
var objs=a.objectives||[];
if(!objs.length) continue;
var allDone=true;
for(var j=0;j<objs.length;j++){
var o=objs[j];
if(o.type==="flag"){
var fk=String(o.finish||"").replace(/^\$/,"");
if(!V[fk]){allDone=false;break;}
}else{
var ck=String(o.current||"").replace(/^\$/,"");
var parts=ck.split(".");
var cur=V[parts[0]];
for(var p=1;p<parts.length;p++) cur=cur?cur[parts[p]]:undefined;
var n=Number(cur);
if(!Number.isFinite(n)||n<Number(o.target)){allDone=false;break;}
}
}
if(allDone) return true;
}
return false;
}catch(e){return false;}
}
requestAnimationFrame(function(){
var dot=document.getElementById("pm2AchDot");
if(dot&&hasUnclaimedAchReward()) dot.style.display="block";
});
})();
<</script>><</if>>
/* ------------------------------------ | UIBAR ON | ------------------------------------ */
<<if !_pmOpen>>
<img src="assets/logo.png" style="max-width:233px; max-height:233px; min-height:120px; min-width:120px;">
<style>.version{font-size:16px;opacity:.8;margin:-2px 0 6px 0}</style>
<div class="version">v.0.A110925</div>
<hr>
<span id="storyBtnWrap" class="story-btn">
<div class="actions">
<span id="storyActionWrap"><<link "Story">><<QuestStory>><</link>></span>
</div>
<<if $StartStory == true>>
<br>
<div class="actions"><<link "Inventory">><<Inventory>><</link>></div>
<br>
<div class="actions"><<link "Taxi">><<Taxi>><</link>></div>
<div class="actionsmail">
<<if $MailInBox == true>>
<br>
<<link "New E-Mail!">><<goto "Email">><</link>>
<</if>>
</div>
<</if>>
<hr>
<div class="linkactions"><<link "Support Game">><<SupportMenu>><</link>></div>
<div class="linkactions"><<link "Cheat">><<CheatMenu>><</link>></div><style>
:root { --br:#262a36; --txt:#e7e9ee; --muted:#aab0bd; --accent:#7aa2ff; --good:#2ecc71; --warn:#f1c40f; --bad:#e74c3c; }
.sc { font-family: ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Ubuntu, Arial; color: var(--txt); max-width: 680px; margin: 0 auto; line-height: 1; }
.row .val.badge { position: relative; }
.valnum { display: inline-block; width: 100%; text-align: center; }
.maxhint { font-size: 10px; opacity: .5; position: absolute; right: 10px; top: 50%; transform: translateY(-65%); margin: 0; display: inline-flex !important; align-items: center !important; justify-content: center !important; line-height: 1; pointer-events: none; }
.sc .grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 0; }
.row { display: flex; align-items: center; justify-content: flex-start; gap: 6px; padding: 0 6px; border: none; border-radius: 6px; background: transparent; text-align: left; height: 28px; width: 100%; }
.row .ic { width: 20px; text-align: left; font-size: 16px; }
.row .lb { flex: 1; color: var(--muted); font-weight: 500; font-size: 0.95em; }
.row .val { display: flex; align-items: center; justify-content: center; height: 26px; min-width: 93px; max-width: 93px; text-align: center; font-weight: 600; font-size: 0.95em; white-space: nowrap; vertical-align: middle; }
.badge { display: inline-flex; align-items: center; justify-content: center; height: 25px; padding: 0 10px; border-radius: 999px; border: 1px solid rgba(255,255,255,.1); background: rgba(255,255,255,.04); font-size: 0.9em; line-height: 25px; }
.row .val.reputation { min-width: 93px; max-width: 93px; }
.badge.energy { color: var(--good); border-color: rgba(46,204,113,.35); }
.badge.stress { color: var(--bad); border-color: rgba(231,76,60,.35); }
.reputation { color: var(--accent); border-color: rgba(60,76,150,.35); }
.actions { display: flex; flex-direction: column; align-items: center; justify-content: center; width: 100%; gap: 3px; margin: 0; padding: 0; }
.actions a, .actions .macro-link, .actions .link-internal { display: flex; align-items: center; justify-content: center; width: 100%; max-width: 680px; height: 30px; border-radius: 6px; border: 1px solid rgba(255,255,255,.1); background: rgba(255,255,255,.03); color: var(--txt); font-size: 0.9em; text-decoration: none; text-align: center; font-weight: 500; transition: background 0.15s ease, transform 0.1s ease; }
.actions a:hover, .actions .macro-link:hover, .actions .link-internal:hover { background: rgba(255,255,255,.06); transform: translateY(-1px); }
.actionsmail a, .actionsmail .macro-link, .actionsmail .link-internal { display: flex; align-items: center; justify-content: center; width: 100%; max-width: 680px; height: 30px; border-radius: 6px; border: 1px solid rgba(231,76,60,.1); background: rgba(231,76,60,.05); color: var(--txt); font-size: 0.9em; text-decoration: none; text-align: center; font-weight: 500; transition: background 0.15s ease, transform 0.1s ease; }
.actionsmail a:hover, .actionsmail .macro-link:hover, .actionsmail .link-internal:hover { background: rgba(231,76,60,.10); transform: translateY(-1px); }
.linkactions { display: flex; flex-direction: column; align-items: center; justify-content: center; width: 100%; gap: 3px; margin: 0; padding: 0; }
.linkactions a, .linkactions .macro-link, .linkactions .link-internal { display: flex; align-items: center; justify-content: center; width: 100%; max-width: 680px; height: 30px; border-radius: 6px; border: 1px solid rgba(100,100,255,.2); background: rgba(100,100,255,.08); color: var(--txt); font-size: 0.9em; text-decoration: none; text-align: center; font-weight: 500; transition: background 0.15s ease, transform 0.1s ease; }
.linkactions a:hover, .linkactions .macro-link:hover, .linkactions .link-internal:hover { background: rgba(100,100,255,.06); transform: translateY(-1px); }
</style><</if>>
/* ---------------------------- | CONTINUOUSLY VERIFIED | --------------------------- */
/* ---------- Travel Per Time ---------- */
<<if $TravelPerTime > 6>><<set $Time += 1>><<set $TravelPerTime = 0>><<Refresh>><</if>>
<<set $LastTime to ($LastTime is undefined) ? $Time : $LastTime>><<if $Time != $LastTime>><<set $LastTime = $Time>><<if $TravelPerTime >= 1>><<set $TravelPerTime = 0>><</if>><</if>>
/* ---------- Time ---------- */
<<if $Time >= 4>><<goto "Sleep">><</if>>
/* ---------- Hour ---------- */
<<if $Hour == 6>>
<<set $Energy-->>
<<set $Time++>>
<<set $Hour = 0>>
<<run setTimeout(function(){var S=SugarCube, dest=S.State.variables.ReturnTo||"MCBedroom"; S.Engine.play(dest);},0)>>
<</if>>
/* ---------- Energy ---------- */
<<if $Energy > $EnergyMax>><<set $Energy = $EnergyMax>><</if>>
<<if $Energy <= 0>><<goto "Sleep">><</if>>
<<set _fitBonus = Math.floor($Fitness / 20)>>
<<set $EnergyMax = $EnergyMaxBase + _fitBonus>>
/* ---------- Heal ---------- */
<<if $Heal > $HealMax>><<set $Heal = $HealMax>><</if>>
/* ---------- Stress ---------- */
<<if $Stress >= 300>>
<<set $Stress = 0>>
<<goto "End.Stress">>
<<else>>
<<set _newPenalty = 0>>
<<if $Stress >= 250>><<set _newPenalty = 4>>
<<elseif $Stress >= 200>><<set _newPenalty = 3>>
<<elseif $Stress >= 150>><<set _newPenalty = 2>>
<<elseif $Stress >= 100>><<set _newPenalty = 1>>
<</if>>
<<set $EnergyMax += ($StressPenalty - _newPenalty)>>
<<set $StressPenalty = _newPenalty>>
<</if>>
<<if $Stress < $StressMin>><<set $Stress = $StressMin>><</if>>
/* ---------- Psychic Power ---------- */
<<if $StartStory == true>>
<<if $PsychicPower > $PsychicPowerMax>>
<<set $PsychicPower = $PsychicPowerMax>>
<</if>>
<</if>>
<<if $PsychicPower <= -1>><<set $PsychicPower = 0>><</if>>
/* ---------- Fitness ---------- */
<<if $Fitness >= $FitnessMax>><<set $Fitness = $FitnessMax>><</if>>
/* ---------- Mail ---------- */
<<if !$MailRead>><<set $MailRead={}>><</if>>
<<set $MailInBox = setup.MailList.some(function(mm){var S=window.SugarCube||window;var Vars=(S.State&&S.State.variables)||{};return !$MailRead[mm.id] && (Vars[mm.id]===true || (mm.id==="StartStoryMail" && Vars.StartStoryMail===false));})>>
/* ---------- Active Mail ---------- */
<<if $NPCPrincipal.lvl >= 1>><<set $UniversityHiringProfessor = true>><</if>>
/* ---------- Day Left System ---------- */
<<if $Day == $SearchWorkDayInt + 1>><<set $SearchWorkMail = true>><</if>>
<<if $Day == $GymSubDayInt + 10>><<set $GymSub = false>><</if>>
<<if $Day == $UniversityHiringDayInt + 3>><<set $UniversityHiringSMS = true>><</if>>
<<if $Day == $NPCPrincipalMailTalklvl0DayInt + 3>><<set $UniversitySummonsMail = true>><</if>>
/* ---------- NPC Principal Mail & SMS ---------- */
<<if $NPCPrincipal.met == true and $NPCPrincipalMailSend0 == false>>
<<set $NPCPrincipalMailTalklvl0DayInt = $Day>>
<<set $NPCPrincipalMailSend0 = true>>
<</if>>
<<if $NPCPrincipal.lvl >= 2 and $NPCPrincipalSMSSend3 == false>>
<<if $MakeUniversityClass3 >= 2>>
<<set $NPCPrincipalSMSTalklvl3DayInt = $Day>>
<<set $NPCPrincipalSMSSend3 = true>>
<</if>>
<</if>>
<<if $NPCPrincipal.lvl >= 4 and $NPCPrincipalSMSSend5 == false>>
<<if $MakeUniversityClass6 >= 1>>
<<set $NPCPrincipalSMSTalklvl5DayInt = $Day>>
<<set $NPCPrincipalSMSSend5 = true>>
<</if>>
<</if>>
<<if $NPCPrincipal.lvl >= 6 and $NPCPrincipalSMSSend6 == false>>
<<set $NPCPrincipalSMSTalklvl6DayInt = $Day>>
<<set $NPCPrincipalSMSSend6 = true>>
<</if>>
<<if $Day == $NPCPrincipalSMSTalklvl3DayInt + 5>><<set $NPCPrincipalSMSTalklvl3 = true>><</if>>
<<if $Day == $NPCPrincipalSMSTalklvl5DayInt + 3>><<set $NPCPrincipalSMSTalklvl5 = true>><</if>>
<<if $Day == $NPCPrincipalSMSTalklvl6DayInt + 3>><<set $NPCPrincipalSMSTalklvl6 = true>><</if>>
<<if $NPCPrincipal.talklvl == 5 and $PrincipalChapter6End == false>>
<<set $PrincipalChapterCurrent5 = true>>
<<elseif $NPCPrincipal.talklvl < 5 and $PrincipalChapter6End == false>>
<<set $PrincipalChapterCurrent5 = false>>
<</if>>
/* ---------- NPC Mayor SMS ---------- */
<<if $NPCMayor.lvl >= 1 and $NPCMayorSMSSend1 == false>>
<<set $NPCMayorSMSTalklvl1DayInt = $Day>>
<<set $NPCMayorSMSSend1 = true>>
<</if>>
<<if $NPCMayor.lvl >= 2 and $NPCMayorSMSSend2 == false>>
<<set $NPCMayorSMSTalklvl2DayInt = $Day>>
<<set $NPCMayorSMSSend2 = true>>
<</if>>
<<if $NPCMayor.lvl >= 5 and $NPCMayorSMSSend5 == false>>
<<set $NPCMayorSMSTalklvl5DayInt = $Day>>
<<set $NPCMayorSMSSend5 = true>>
<</if>>
<<if $Day == $NPCMayorSMSTalklvl1DayInt + 5>><<set $NPCMayorSMSTalklvl1 = true>><</if>>
<<if $Day == $NPCMayorSMSTalklvl2DayInt + 5>><<set $NPCMayorSMSTalklvl2 = true>><</if>>
<<if $Day == $NPCMayorSMSTalklvl5DayInt + 3>><<set $NPCMayorSMSTalklvl5 = true>><</if>>
/* ---------- NPC Housemate Female SMS ---------- */
<<if $NPCHousemateFemale.lvl == 5 and $NPCHousemateFemaleSMSSend5 == false>>
<<set $NPCHousemateFemaleSMSTalklvl5DayInt = $Day>>
<<set $NPCHousemateFemaleSMSSend5 = true>>
<</if>>
<<if $Day == $NPCHousemateFemaleSMSTalklvl5DayInt + 1>><<set $NPCHousemateFemaleSMSTalklvl5 = true>><</if>>
/* ---------- NPC Landlady Talk Corruption ---------- */
<<if $NPCLandlady.lvl == 1 and $NPCLandladyTalkCorruptionSend1 == false>>
<<if $NPCHousemateFemale.lvl >= 2>>
<<set $NPCLandladyTalkCorruption1DayInt = $Day>>
<<set $NPCLandladyTalkCorruptionSend1 = true>>
<</if>>
<</if>>
<<if $NPCLandlady.lvl == 2 and $NPCLandladyTalkCorruptionSend2 == false>>
<<if $NPCHousemateFemale.lvl >= 3>>
<<set $NPCLandladyTalkCorruption2DayInt = $Day>>
<<set $NPCLandladyTalkCorruptionSend2 = true>>
<</if>>
<</if>>
<<if $NPCLandlady.lvl == 3 and $NPCLandladyTalkCorruptionSend3 == false>>
<<if $NPCHousemateFemale.lvl >= 4>>
<<set $NPCLandladyTalkCorruption3DayInt = $Day>>
<<set $NPCLandladyTalkCorruptionSend3 = true>>
<</if>>
<</if>>
<<if $NPCLandlady.lvl == 5 and $NPCLandladyTalkCorruptionSend5 == false>>
<<if $SedativesBought == true>>
<<set $NPCLandladyTalkCorruption5DayInt = $Day>>
<<set $NPCLandladyTalkCorruptionSend5 = true>>
<</if>>
<</if>>
<<if $Day == $NPCLandladyTalkCorruption1DayInt + 3>>
<<set $NPCLandladyCorruptionTalklvl1 = true>>
<</if>>
<<if $Day == $NPCLandladyTalkCorruption2DayInt + 3>>
<<set $NPCLandladyCorruptionTalklvl2 = true>>
<</if>>
<<if $Day == $NPCLandladyTalkCorruption3DayInt + 3>>
<<set $NPCLandladyCorruptionTalklvl3 = true>>
<</if>>
<<if $Day == $NPCLandladyTalkCorruption5DayInt + 3>>
<<set $SedativesDeliveredWaiting = true>>
<</if>>
<<if $Spycam.bathroom == true and $Story4_5Finish == true>>
<<set $NPCLandladyChapter5 = true>>
<</if>>
/* ---------- NPC Neighbor At Home ---------- */
<<if $Time == 0>>
<<set $NPCRightNeighbor.athome = true>>
<<else>>
<<set $NPCRightNeighbor.athome = false>>
<</if>>
/* ---------- NPC BestFriend SMS ---------- */
<<if $NPCBestFriend.lvl >= 2 and $NPCBestFriendSMSSend2 == false>>
<<set $NPCBestFriendSMSTalklvl2DayInt = $Day>>
<<set $NPCBestFriendSMSSend2 = true>>
<</if>>
<<if $Day == $NPCBestFriendSMSTalklvl2DayInt + 3>>
<<set $NPCBestFriendSMSTalklvl2 = true>>
<</if>>
/* ---------- NPC Classmate 1 ---------- */
<<if $Inventory.necklace>>
<<set $NecklaceBought = true>>
<</if>>
/* ---------- NPC Classmate 3 SMS ---------- */
<<if $NPCMate3.lvl >= 5 and $NPCMate3SMSSend5 == false>>
<<set $NPCMate3SMSTalklvl5DayInt = $Day>>
<<set $NPCMate3SMSSend5 = true>>
<</if>>
<<if $Day == $NPCMate3SMSTalklvl5DayInt + 3>>
<<set $NPCMate3SMSTalklvl5 = true>>
<</if>>
<<if $Inventory.harness>>
<<set $HarnessBought = true>>
<</if>>
/* ---------- Story ---------- */
<<if $NPCMayor.lvl >= 3 and $MayorStory1InitDayInt == false>>
<<if $MayorStoryInfo5 == true>>
<<set $MayorStory1DayInt = $Day>>
<<set $MayorStory1InitDayInt = true>>
<</if>>
<</if>>
<<if $NPCMayor.lvl >= 3 and $MayorStory2InitDayInt == false>>
<<if $MayorStoryInfo6 == true>>
<<set $MayorStory2DayInt = $Day>>
<<set $MayorStory2InitDayInt = true>>
<</if>>
<</if>>
<<if $NPCMayor.lvl >= 3 and $MayorStory3InitDayInt == false>>
<<if $MayorStoryInfo8 == true>>
<<set $MayorStory3DayInt = $Day>>
<<set $MayorStory3InitDayInt = true>>
<</if>>
<</if>>
<<if $NPCMayor.lvl >= 4 and $MayorStory4InitDayInt == false>>
<<if $MayorStoryInfoForSMS == true>>
<<set $MayorStory4DayInt = $Day>>
<<set $MayorStory4InitDayInt = true>>
<</if>>
<</if>>
<<if $NPCMayor.lvl >= 4 and $MayorStory5InitDayInt == false>>
<<if $MayorStoryInfo12 == true>>
<<set $MayorStory5DayInt = $Day>>
<<set $MayorStory5InitDayInt = true>>
<</if>>
<</if>>
<<if $NPCMayor.lvl >= 5 and $MayorStory6InitDayInt == false>>
<<if $MayorStoryInfo13 == true>>
<<set $MayorStory6DayInt = $Day>>
<<set $MayorStory6InitDayInt = true>>
<</if>>
<</if>>
<<if $Day == $MayorStory1DayInt + 5>>
<<set $MayorStoryEncounter1 = true>>
<</if>>
<<if $Day == $MayorStory2DayInt + 5>>
<<set $MayorStoryEncounter2 = true>>
<</if>>
<<if $Day == $MayorStory3DayInt + 1>>
<<set $MayorStoryEncounter3 = true>>
<</if>>
<<if $Day == $MayorStory4DayInt + 5>>
<<set $MayorStoryInfoSMS1 = true>><
</if>>
<<if $Day == $MayorStory5DayInt + 2>>
<<set $MayorStoryInfoMail1 = true>>
<</if>>
<<if $Day == $MayorStory6DayInt + 1>>
<<set $MayorStoryInfo14 = true>>
<</if>>
/* ---------- Shop Reputation Gain ---------- */
<<for _shop range [$ShopCar, $ShopClothing]>>
<<for _item range _shop>>
<<if _item.bought and !_item.repApplied>>
<<set $Reputation += (_item.rep || 0)>>
<<set _item.repApplied = true>>
<</if>>
<</for>>
<</for>>
/* ---------- Interaction ---------- */
<<if $InteractInInterior == false>>
<<if $Corruption.city >= 4>>
<<set $InteractInInterior = true>>
<<elseif $Corruption.city < 4>>
<<set $InteractInInterior = false>>
<</if>>
<</if>>
/* -------------------------------- NPC CORRUPTION -------------------------------- */
<<script>>
(function(){
var V = State.variables;
var npcs = [
'NPCHousemateFemale','NPCHousemateMale','NPCLandlady','NPCLandlord',
'NPCOnlineFriend','NPCLeftNeighbor','NPCRightNeighbor','NPCBestFriend',
'NPCMate1','NPCMate2','NPCMate3','NPCTeachSport','NPCTeachTech',
'NPCTeachLang','NPCPrincipal','NPCBossGym','NPCBossMarket',
'NPCMayor','NPCHomeless','NPCSexShop'
];
npcs.forEach(function(key){
var npc = V[key];
if(npc && npc.lastCorruptBool === true && V.Day >= npc.lastCorruptDay + 1){
npc.lastCorruptBool = false;
npc.lastCorruptDay = -9;
}
});
})();
<</script>>
/* ---------------------------- UPGRADE PC COMPONENT ---------------------------- */
<<script>>
(function(){
var V = State.variables;
var items = V.ShopElectronic;
var upgrades = {
"Motherboard2": ["PCMotherboard", "MSI MAG B650 Tomahawk WiFi", 2],
"Motherboard3": ["PCMotherboard", "ASUS ROG Crosshair X670E Hero", 3],
"cpu2": ["PCcpu", "AMD Ryzen 5 7600", 2],
"cpu3": ["PCcpu", "AMD Ryzen 9 7950X3D", 3],
"gpu2": ["PCgpu", "NVIDIA GeForce RTX 4070", 2],
"gpu3": ["PCgpu", "ASUS ROG Strix GeForce RTX 4090 OC 24GB", 3],
"ram2": ["PCram", "Corsair Vengeance 32GB (2x16) DDR5-6000 CL36 (EXPO)", 2],
"ram3": ["PCram", "G.SKILL Trident Z5 Neo 64GB (2x32) DDR5-6000 (EXPO)", 3],
"stockage2": ["PCstockage", "WD_BLACK SN770 2TB NVMe", 2],
"stockage3": ["PCstockage", "Samsung 990 PRO 2TB NVMe 2x", 3],
"os2": ["PCos", "Windows 7 Ultimate", 2],
"os3": ["PCos", "Windows 11 Pro", 3],
"screen2": ["PCscreen", "Gigabyte M27Q 27, 2560x1440, 165/170 Hz", 2],
"screen3": ["PCscreen", "LG UltraGear 27GP950-B 27, 4K, 144 Hz, HDMI 2.1", 3],
"keyboard2": ["PCkeyboard", "Logitech K120", 2],
"keyboard3": ["PCkeyboard", "Keychron Q1 Pro", 3],
"mouse2": ["PCmouse", "Logitech G305 LIGHTSPEED", 2],
"mouse3": ["PCmouse", "Razer Viper V3 Pro", 3],
"headset2": ["PCheadset", "HyperX Cloud II", 2],
"headset3": ["PCheadset", "SteelSeries Arctis Nova Pro Wireless", 3],
"microphone1": ["PCmicrophone", "Trust GXT 212 Mico USB", 1],
"microphone2": ["PCmicrophone", "Blue Yeti USB", 2],
"microphone3": ["PCmicrophone", "Shure SM7B + Focusrite Scarlett 2i2 (3rd Gen)", 3],
"camera1": ["PCcamera", "Logitech C270 HD", 1],
"camera2": ["PCcamera", "Logitech C920 HD Pro", 2],
"camera3": ["PCcamera", "Sony ZV-E10 + Sigma 16 mm f/1.4 DC DN", 3],
};
if(!items) return;
items.forEach(function(item){
if(!item.bought) return;
var u = upgrades[item.id];
if(!u) return;
var varName = u[0];
var newName = u[1];
var newImg = u[2];
if(V[varName] && newImg > V[varName].img){
V[varName].name = newName;
V[varName].img = newImg;
V.FirstBoughtComponent = true;
}
});
})();
<</script>>
/* ----------------------------------- STORY UPDATE ---------------------------------- */
<<script>>(function(){"use strict";if(window.__StoryWatchInit)return;window.__StoryWatchInit=true;var VARS=["Story1_1Current","Story1_2Current","Story1_3Current","Story2_1Current","Story2_2Current","Story2_3Current","Story3_1Current","Story3_2Current","Story3_3Current","Story3_4Current","Story4_1Current","Story4_2Current","Story4_3Current","Story4_4Current","Story4_5Current","Story5_1Current","Story5_2Current","Story6_1Current","Story6_1Current","Story6_2Current","Story6_3Current","Story6_4Current","Story6_5Current","Story6_6Current","Story6_7Current","Story6_8Current","Story6_9Current","Story6_10Current","Story6_11Current","Story6_12Current","Story7_1Current","Story7_2Current","Story7_3Current","Story8_1Current","Story8_2Current","Story9_1Current","Story9_2Current","Story9_3Current","Story9_4Current","Story10_1Current","Story10_2Current","Story11_1Current","Story11_2Current","Story11_3Current","Story12_1Current","Story12_2Current","Story13_1Current","Story14_1Current","Story14_2Current","Story14_3Current","Story15_1Current","Story15_2Current","Story16_1Current","Story16_2Current"];function ensureStyle(){if(document.getElementById("storyWatchStyle"))return;var s=document.createElement("style");s.id="storyWatchStyle";s.textContent=".actions #storyActionWrap{position:relative;display:block;width:100%;}.actions #storyActionWrap.hasUpdate a{animation:storyPulse 1.1s ease-in-out infinite;border-color:rgba(255,80,80,.55)!important;background:rgba(255,80,80,.10)!important;box-shadow:0 0 14px rgba(255,80,80,.22)!important;}@keyframes storyPulse{0%{transform:scale(1);}55%{transform:scale(1.02);}100%{transform:scale(1);}}.actions #storyActionWrap .storyBadge{position:absolute;top:4px;right:10px;min-width:18px;height:18px;padding:0 6px;border-radius:999px;background:#d33;color:#fff;font-size:12px;line-height:18px;text-align:center;font-weight:700;display:none;pointer-events:none;}.actions #storyActionWrap.hasUpdate .storyBadge{display:inline-block;}#storyToast{position:fixed;right:16px;bottom:16px;background:rgba(20,20,20,.92);border:1px solid rgba(255,255,255,.12);color:#f2f2f2;padding:10px 12px;border-radius:10px;font-size:.95rem;opacity:0;transform:translateY(10px);pointer-events:none;z-index:9999;}#storyToast.show{animation:toastInOut 2.4s ease forwards;}@keyframes toastInOut{0%{opacity:0;transform:translateY(10px);}12%{opacity:1;transform:translateY(0);}80%{opacity:1;transform:translateY(0);}100%{opacity:0;transform:translateY(10px);}}";document.head.appendChild(s);}function getStore(){var v=State.variables;if(!v._storyWatch)v._storyWatch={inited:false,last:{},updated:false};return v._storyWatch;}function snap(){var s={};for(var i=0;i<VARS.length;i++){var k=VARS[i];s[k]=!!State.variables[k];}return s;}function hasDiff(a,b){for(var k in b){if(a[k]!==b[k])return true;}return false;}function ensureBadge(){var w=document.getElementById("storyActionWrap");if(!w)return;if(!w.querySelector(".storyBadge")){var b=document.createElement("span");b.className="storyBadge";b.textContent="!";w.appendChild(b);}}function toast(msg){var el=document.getElementById("storyToast");if(!el){el=document.createElement("div");el.id="storyToast";document.body.appendChild(el);}el.textContent=msg;el.classList.remove("show");void el.offsetWidth;el.classList.add("show");}function apply(){var w=document.getElementById("storyActionWrap");if(!w)return;var store=getStore();ensureBadge();w.classList.toggle("hasUpdate",!!store.updated);}function tick(){var store=getStore();var now=snap();if(!store.inited){store.inited=true;store.last=now;apply();return;}if(hasDiff(store.last,now)){store.last=now;store.updated=true;toast("Story updated. New objective available.");}apply();}ensureStyle();setInterval(tick,400);setTimeout(tick,0);})();<</script>>/* ---===[=•=]===--- | SAVE GAME OPTIONS | ---===[=•=]===--- */
<<script>>
(function(){
var AUDIO_KEY = "sc_audio_bus_v1";
try {
var raw = localStorage.getItem(AUDIO_KEY);
if (raw) {
var obj = JSON.parse(raw);
if (obj && typeof obj === "object") {
function clamp01(v){ v=+v||0; return v<0?0:(v>1?1:v); }
function tryApply(){
var m = (window.setup && setup.AudioMixer) ? setup.AudioMixer : (window.AudioMixer || null);
if (!m || typeof m.setVolume !== "function") return false;
for (var bus in obj) { m.setVolume(bus, clamp01(obj[bus])); }
return true;
}
if (!tryApply()) {
var tries = 0;
var id = setInterval(function(){
if (tryApply() || ++tries > 60) clearInterval(id);
}, 200);
}
}
}
} catch(e) {}
var OPTS_KEY = "sc_options_v1";
try {
var optsRaw = localStorage.getItem(OPTS_KEY);
var saved = optsRaw ? JSON.parse(optsRaw) : {};
if (!saved || typeof saved !== "object") saved = {};
var V = State.variables;
if (typeof saved.OptSkipMiniGamesOn !== "undefined") V.OptSkipMiniGamesOn = saved.OptSkipMiniGamesOn;
else if (typeof V.OptSkipMiniGamesOn === "undefined") V.OptSkipMiniGamesOn = false;
if (typeof saved.OptFontSize !== "undefined") V.OptFontSize = saved.OptFontSize;
else if (typeof V.OptFontSize === "undefined") V.OptFontSize = 0;
if (typeof saved.OptAllowGay !== "undefined") V.OptAllowGay = saved.OptAllowGay;
else if (typeof V.OptAllowGay === "undefined") V.OptAllowGay = true;
if (typeof saved.OptAllowFuta !== "undefined") V.OptAllowFuta = saved.OptAllowFuta;
else if (typeof V.OptAllowFuta === "undefined") V.OptAllowFuta = true;
if (typeof saved.OptLanguage !== "undefined") V.OptLanguage = saved.OptLanguage;
else if (typeof V.OptLanguage === "undefined") V.OptLanguage = "English";
if (typeof saved.OptWindowMode !== "undefined") V.OptWindowMode = saved.OptWindowMode;
else if (typeof V.OptWindowMode === "undefined") V.OptWindowMode = "fullscreen";
} catch(e) {}
})();
<</script>>
/* ---===[=•=]===--- | STORY | ---===[=•=]===--- */
<<set $Story1_1Finish = false>> <<set $Story1_1Current = true>>
<<set $Story1_2Finish = false>> <<set $Story1_2Current = false>>
<<set $Story2_1Finish = false>> <<set $Story2_1Current = false>>
<<set $Story2_2Finish = false>> <<set $Story2_2Current = false>>
<<set $Story2_3Finish = false>> <<set $Story2_3Current = false>>
<<set $Story3_1Finish = false>> <<set $Story3_1Current = false>>
<<set $Story3_2Finish = false>> <<set $Story3_2Current = false>>
<<set $Story3_3Finish = false>> <<set $Story3_3Current = false>>
<<set $Story3_4Finish = false>> <<set $Story3_4Current = false>>
<<set $Story4_1Finish = false>> <<set $Story4_1Current = false>>
<<set $Story4_2Finish = false>> <<set $Story4_2Current = false>>
<<set $Story4_3Finish = false>> <<set $Story4_3Current = false>>
<<set $Story4_4Finish = false>> <<set $Story4_4Current = false>>
<<set $Story4_5Finish = false>> <<set $Story4_5Current = false>>
<<set $Story5_1Finish = false>> <<set $Story5_1Current = false>>
<<set $Story5_2Finish = false>> <<set $Story5_2Current = false>>
<<set $Story6_1Finish = false>> <<set $Story6_1Current = false>>
<<set $Story6_2Finish = false>> <<set $Story6_2Current = false>>
<<set $Story6_3Finish = false>> <<set $Story6_3Current = false>>
<<set $Story6_4Finish = false>> <<set $Story6_4Current = false>>
<<set $Story6_5Finish = false>> <<set $Story6_5Current = false>>
<<set $Story6_6Finish = false>> <<set $Story6_6Current = false>>
<<set $Story6_7Finish = false>> <<set $Story6_7Current = false>>
<<set $Story6_8Finish = false>> <<set $Story6_8Current = false>>
<<set $Story6_9Finish = false>> <<set $Story6_9Current = false>>
<<set $Story6_10Finish = false>> <<set $Story6_10Current = false>>
<<set $Story6_11Finish = false>> <<set $Story6_11Current = false>>
<<set $Story6_12Finish = false>> <<set $Story6_12Current = false>>
<<set $Story7_1Finish = false>> <<set $Story7_1Current = false>>
<<set $Story7_2Finish = false>> <<set $Story7_2Current = false>>
<<set $Story7_3Finish = false>> <<set $Story7_3Current = false>>
<<set $Story8_1Finish = false>> <<set $Story8_1Current = false>>
<<set $Story8_2Finish = false>> <<set $Story8_2Current = false>>
<<set $Story9_1Finish = false>> <<set $Story9_1Current = false>>
<<set $Story9_2Finish = false>> <<set $Story9_2Current = false>>
<<set $Story9_3Finish = false>> <<set $Story9_3Current = false>>
<<set $Story9_4Finish = false>> <<set $Story9_4Current = false>>
<<set $Story10_1Finish = false>> <<set $Story10_1Current = false>>
<<set $Story10_2Finish = false>> <<set $Story10_2Current = false>>
<<set $Story11_1Finish = false>> <<set $Story11_1Current = false>>
<<set $Story11_2Finish = false>> <<set $Story11_2Current = false>>
<<set $Story11_3Finish = false>> <<set $Story11_3Current = false>>
<<set $Story12_1Finish = false>> <<set $Story12_1Current = false>>
<<set $Story12_2Finish = false>> <<set $Story12_2Current = false>>
<<set $Story13_1Finish = false>> <<set $Story13_1Current = false>>
<<set $Story13_2Finish = false>> <<set $Story13_2Current = false>>
<<set $Story14_1Finish = false>> <<set $Story14_1Current = false>>
<<set $Story14_2Finish = false>> <<set $Story14_2Current = false>>
<<set $Story14_3Finish = false>> <<set $Story14_3Current = false>>
<<set $Story15_1Finish = false>> <<set $Story15_1Current = false>>
<<set $Story15_2Finish = false>> <<set $Story15_2Current = false>>
<<set $Story16_1Finish = false>> <<set $Story16_1Current = false>>
<<set $Story16_2Finish = false>> <<set $Story16_2Current = false>>
<<set $StartStory = false>>
<<set $StartStoryMail = false>>
<<set $SearchWork = false>>
<<set $SearchWorkMail = false>>
<<set $SearchWorkMailEnd = false>>
<<set $InterviewWorkArena = false>>
<<set $TalkDealer1 = false>>
<<set $TalkDealer2 = false>>
<<set $TalkDealer3 = false>>
<<set $UniversityHiring = false>>
<<set $UniversityJob = false>>
<<set $PlayerWorkUniversity = false>>
<<set $PrincipalChapterCurrent5 = false>>
<<set $MakeUniversityClass1 = 0>>
<<set $MakeUniversityClass2 = 0>>
<<set $MakeUniversityClass3 = 0>>
<<set $MakeUniversityClass4 = 0>>
<<set $MakeUniversityClass5 = 0>>
<<set $MakeUniversityClass6 = 0>>
<<set $MayorStoryInfo1 = false>>
<<set $MayorStoryInfo2 = false>>
<<set $MayorStoryInfo3 = false>>
<<set $MayorStoryInfo4 = false>>
<<set $MayorStoryInfo5 = false>>
<<set $MayorStory1DayInt = -9999>>
<<set $MayorStory1InitDayInt = false>>
<<set $MayorStoryEncounter1 = false>>
<<set $MayorStoryEncounter1Goto = false>>
<<set $MayorStoryInfo6 = false>>
<<set $MayorStory2DayInt = -9999>>
<<set $MayorStory2InitDayInt = false>>
<<set $MayorStoryEncounter2 = false>>
<<set $MayorStoryEncounter2Goto = false>>
<<set $MayorStoryInfo7 = false>>
<<set $MayorStoryInfo8 = false>>
<<set $MayorStory3DayInt = -9999>>
<<set $MayorStory3InitDayInt = false>>
<<set $MayorStoryEncounter3 = false>>
<<set $MayorStoryEncounter3Goto = false>>
<<set $MayorStoryInfo9 = false>>
<<set $MayorStoryInfoForSMS = false>>
<<set $MayorStory4DayInt = -9999>>
<<set $MayorStory4InitDayInt = false>>
<<set $MayorStoryInfoSMS1 = false>>
<<set $MayorStoryInfo10 = false>>
<<set $MayorStoryInfo11 = false>>
<<set $MayorStoryInfo12 = false>>
<<set $MayorStory5DayInt = -9999>>
<<set $MayorStory5InitDayInt = false>>
<<set $MayorStoryInfoMail1 = false>>
<<set $MayorStoryInfo13 = false>>
<<set $MayorStory6DayInt = -9999>>
<<set $MayorStory6InitDayInt = false>>
<<set $MayorStoryInfo14 = false>>
<<set $MayorStoryFinish = false>>
<<set $Key = {
university: false,
cityhall: false,
sexshop: false,
stripclub: false,
}>>
<<set $Corruption = {
city: 0,
university: 0,
police: 0,
hospital: 0,
mall: 0,
oldtown: 0,
home: 0,
countryside: 0,
}>>
<<set $Spycam = {
bathroom: false,
housematefemale: false,
housematemale: false,
mainbedroom: false,
}>>
<<set $SpycamStepStory = false>>
<<set $SpycamSoftware = false>>
<<set $PlayerHasCar = false>>
<<set $TalkBestFriendChapter5 = false>>
<<set $FirstBoughtComponent = false>>
<<set $FirstEditingSpycam = false>>
/* ---===[=•=]===--- | SETUP INT | ---===[=•=]===--- */
<<set $GameVersion ={
id: 3,
name: "v.0.B260710",
}>>
<<set $ShowUiBar = false>>
<<set $ShowTopUiBar = false>>
<<set $ShowBottomUiBar = false>>
<<set $CheatOn = false>>
<<set $InMainMenu = true>>
<<set $SaveTalklvl = 0>>
<<set $Day = 1>>
<<set $Time = 0>>
<<set $Hour = 0>>
<<set $Energy = 5>>
<<set $EnergyMax = 5>>
<<set $EnergyMaxBase = $EnergyMax>>
<<set $PsychicPower = 3>>
<<set $PsychicPowerMax = 3>>
<<set $PsychicPowerMaxBase = $PsychicPowerMax>>
<<set $Stress = 0>>
<<set $StressMin = 0>>
<<set $StressPenalty = 0>>
<<set $Heal = 100>>
<<set $HealMax = 100>>
<<set $Money = +($Money is undefined ? 100 : $Money)>>
<<set $Bank = +($Bank is undefined ? 250 : $Bank)>>
<<set $Inventory = $Inventory or {}>>
<<set $Fitness = 0>>
<<set $FitnessMax = 100>>
<<set $Reputation = 0>>
<<set $Slavenumber = 0>>
<<set $Soldiernumber = 0>>
<<set $ShowerDayTime = false>>
<<set $FitnessDayTime = false>>
<<set $TravelPerTime = 0>>
<<set $Excitement = 0>>
<<set $GymSub = false>>
<<set $GymSubDayInt = false>>
<<set $InteractInInterior = false>>
<<set $ReturnTo = "">>
<<set $SpectatorsThePit = 0>>
<<set $MailInBox = false>>
<<set setup.MailList = [
{ id:"StartStoryMail", title:"Psychic Powers", pass:"StartStory1", read:false },
{ id:"SearchWorkMail", title:"Responses to Arena job listing", pass:"SearchWork3", read:false },
{ id:"UniversitySummonsMail", title:"Official Summons from the Principal", pass:"UniversitySummons1", read:false },
{ id:"UniversityHiringProfessor", title:"The University Is Looking for a Professor", pass:"UniversityWork1", read:false },
{ id:"MayorStoryInfoMail1", title:"Loan Approval Confirmation - Construction Project Financing", pass:"MayorStory21", read:false },
]>>
<<set $AutoSaveCheck = false>>
<<set $GalleryMedia = $GalleryMedia or {}>>
/* ---===[=•=]===--- | ACHIEVEMENTS | ---===[=•=]===--- */
<<set $Ach_Usebug = false>>
<<set $Ach_Count_Deal_Weed = 0>>
/* ---===[=•=]===--- | ITEMS / SHOPS | ---===[=•=]===--- */
<<set $DealerSellItems = {
1: { "weed": 55, "coke": 85, "meth": 125 },
2: { "weed": 70, "coke": 115, "meth": 165 },
3: { "weed": 95, "coke": 145, "meth": 205 }
}>>
<<set $IllegalItems = ["weed","coke","meth"]>>
<<set $ShopTrapHouse = [
{id:"weed", name:"10-Pack of Weed", price:50, img:"assets/img/items/traphouse/weed.webp", unique:false, inventory:true, bought:false, desc:"Personally, you don't use it, but other people do..."},
{id:"coke", name:"Gram of Snow", price:75, img:"assets/img/items/traphouse/coke.webp", unique:false, inventory:true, bought:false, desc:"Personally, you don't use it, but other people do..."},
{id:"meth", name:"Bag of Ice", price:110, img:"assets/img/items/traphouse/meth.webp", unique:false, inventory:true, bought:false, desc:"Personally, you don't use it, but other people do..."},
]>>
<<set $GiftItemsList = {
"alcool": { aff: 1, cor: 1}, "flower": { aff: 3, cor: 0}, "book": { aff: 2, cor: 0}, "condom": { aff: 0, cor: 2},
}>>
<<set $ShopMarket = [
{id:"alcool", name:"Bottle of alcohol", price:15, img:"assets/img/items/market/alcool.png", unique:false, inventory:true, bought:false, desc:"An item that can be offered..."},
/*
{id:"flower", name:"Bouquet of flowers", price:30, img:"assets/img/items/market/flower.png", unique:false, inventory:true, bought:false, desc:"An item that can be offered..."},
{id:"book", name:"Book", price:20, img:"assets/img/items/market/book.png", unique:false, inventory:true, bought:false, desc:"An item that can be offered..."},
{id:"condom", name:"Condom", price:20, img:"assets/img/items/market/condom.webp", unique:false, inventory:true, bought:false, desc:"An item that can be offered..."},
*/
]>>
<<set $HospitalMarket = [
{id:"Medkit", name:"Medkit", price:50, img:"assets/img/items/hospital/medkit.webp", unique:false, inventory:true, bought:false, desc:"An item that allows you to heal yourself..."},
]>>
<<set $ShopElectronic = [
{id:"spycam", name:"Hidden Camera", price:300, img:"assets/img/items/electronic/spycam.png", unique:false, inventory:true, bought:false, desc:"Can be placed in locations to discreetly film people without their knowledge."},
{id:"camera1", name:"Logitech C270 HD", price:30, img:"assets/img/misc/MCPC/camera1.jpg", unique:true, inventory:false, bought:false, desc:""},
{id:"camera2", name:"Logitech C920 HD Pro", price:60, img:"assets/img/misc/MCPC/camera2.jpg", unique:true, inventory:false, bought:false, desc:""},
{id:"camera3", name:"Sony ZV-E10 + Sigma 16 mm f/1.4 DC DN", price:1420, img:"assets/img/misc/MCPC/camera3.jpg", unique:true, inventory:false, bought:false, desc:""},
{id:"cpu2", name:"AMD Ryzen 5 7600", price:180, img:"assets/img/misc/MCPC/cpu2.jpg", unique:true, inventory:false, bought:false, desc:""},
{id:"cpu3", name:"AMD Ryzen 9 7950X3D", price:1100, img:"assets/img/misc/MCPC/cpu3.jpg", unique:true, inventory:false, bought:false, desc:""},
{id:"gpu2", name:"NVIDIA GeForce RTX 4070", price:600, img:"assets/img/misc/MCPC/gpu2.webp", unique:true, inventory:false, bought:false, desc:""},
{id:"gpu3", name:"ASUS ROG Strix GeForce RTX 4090 OC 24GB", price:2800, img:"assets/img/misc/MCPC/gpu3.jpg", unique:true, inventory:false, bought:false, desc:""},
{id:"headset2", name:"HyperX Cloud II", price:80, img:"assets/img/misc/MCPC/headset2.jpg", unique:true, inventory:false, bought:false, desc:""},
{id:"headset3", name:"SteelSeries Arctis Nova Pro Wireless", price:350, img:"assets/img/misc/MCPC/headset3.webp", unique:true, inventory:false, bought:false, desc:""},
{id:"keyboard2", name:"Logitech K120", price:20, img:"assets/img/misc/MCPC/keyboard2.jpg", unique:true, inventory:false, bought:false, desc:""},
{id:"keyboard3", name:"Keychron Q1 Pro", price:150, img:"assets/img/misc/MCPC/keyboard3.webp", unique:true, inventory:false, bought:false, desc:""},
{id:"microphone1", name:"Trust GXT 212 Mico USB", price:30, img:"assets/img/misc/MCPC/microphone1.jpg", unique:true, inventory:false, bought:false, desc:""},
{id:"microphone2", name:"Blue Yeti USB", price:120, img:"assets/img/misc/MCPC/microphone2.jpg", unique:true, inventory:false, bought:false, desc:""},
{id:"microphone3", name:"Shure SM7B + Focusrite Scarlett 2i2 (3rd Gen)", price:580, img:"assets/img/misc/MCPC/microphone3.jpg", unique:true, inventory:false, bought:false, desc:""},
{id:"Motherboard2", name:"MSI MAG B650 Tomahawk WiFi", price:220, img:"assets/img/misc/MCPC/motherboard2.jpg", unique:true, inventory:false, bought:false, desc:""},
{id:"Motherboard3", name:"ASUS ROG Crosshair X670E Hero", price:1050, img:"assets/img/misc/MCPC/motherboard3.webp", unique:true, inventory:false, bought:false, desc:""},
{id:"mouse2", name:"Logitech G305 LIGHTSPEED", price:45, img:"assets/img/misc/MCPC/mouse2.jpg", unique:true, inventory:false, bought:false, desc:""},
{id:"mouse3", name:"Razer Viper V3 Pro", price:170, img:"assets/img/misc/MCPC/mouse3.jpg", unique:true, inventory:false, bought:false, desc:""},
{id:"os2", name:"Windows 7 Ultimate", price:15, img:"assets/img/misc/MCPC/os2.png", unique:true, inventory:false, bought:false, desc:""},
{id:"os3", name:"Windows 11 Pro", price:259, img:"assets/img/misc/MCPC/os3.png", unique:true, inventory:false, bought:false, desc:""},
{id:"ram2", name:"Corsair Vengeance 32GB (2x16) DDR5-6000 CL36 (EXPO)", price:130, img:"assets/img/misc/MCPC/ram2.jpg", unique:true, inventory:false, bought:false, desc:""},
{id:"ram3", name:"G.SKILL Trident Z5 Neo 64GB (2x32) DDR5-6000 (EXPO)", price:300, img:"assets/img/misc/MCPC/ram3.webp", unique:true, inventory:false, bought:false, desc:""},
{id:"screen2", name:"Gigabyte M27Q 27, 2560x1440, 165/170 Hz", price:230, img:"assets/img/misc/MCPC/screen2.jpg", unique:true, inventory:false, bought:false, desc:""},
{id:"screen3", name:"LG UltraGear 27GP950-B 27, 4K, 144 Hz, HDMI 2.1", price:800, img:"assets/img/misc/MCPC/screen3.jpg", unique:true, inventory:false, bought:false, desc:""},
{id:"stockage2", name:"WD_BLACK SN770 2TB NVMe", price:150, img:"assets/img/misc/MCPC/stockage2.webp", unique:true, inventory:false, bought:false, desc:""},
{id:"stockage3", name:"Samsung 990 PRO 2TB NVMe 2x", price:400, img:"assets/img/misc/MCPC/stockage3.webp", unique:true, inventory:false, bought:false, desc:""}
]>>
<<set $ShopCar = [
{id:"scooter", name:"Scooter", price:1000, img:"assets/img/items/car/scooter.png", unique:true, inventory:false, bought:false, rep:10, desc:"+10 Reputation"},
{id:"car1", name:"Basic Car", price:5000, img:"assets/img/items/car/car1.png", unique:true, inventory:false, bought:false, rep:50, desc:"+50 Reputation"},
]>>
<<set $ShopClothing = [
{id:"tshirt1", name:"Basic T-Shirt", price:25, img:"assets/img/items/clothing/tshirt1.png", unique:true, inventory:false, bought:false, rep:10, desc:"+10 Reputation"},
{id:"pants1", name:"Basic Pants", price:50, img:"assets/img/items/clothing/pants1.png", unique:true, inventory:false, bought:false, rep:20, desc:"+20 Reputation"},
{id:"shoes1", name:"Basic Shoes", price:50, img:"assets/img/items/clothing/shoes1.png", unique:true, inventory:false, bought:false, rep:20, desc:"+20 Reputation"},
]>>
<<set $ShopSexshop = [
{id:"necklace", name:"Chain necklace", price:30, img:"assets/img/items/sexshop/necklace.webp", unique:true, inventory:true, bought:false, desc:"An item that can be offered..."},
{id:"harness", name:"Body harness", price:30, img:"assets/img/items/sexshop/harness.webp", unique:true, inventory:true, bought:false, desc:"An item that can be offered..."},
]>>
/* ---===[=•=]===--- | CHARACTERS | ---===[=•=]===--- */
/* --- NPCHousemateFemale SMS --- */
<<set $NPCHousemateFemaleSMSTalklvl5DayInt = -9999>>
<<set $NPCHousemateFemaleSMSTalklvl5 = false>>
<<set $NPCHousemateFemaleSMSSend5 = false>>
/* --- NPCLandlady Talk Corruption --- */
<<set $NPCLandladyTalkCorruption1DayInt = -9999>>
<<set $NPCLandladyTalkCorruptionSend1 = false>>
<<set $NPCLandladyCorruptionTalklvl1 = false>>
<<set $NPCLandladyTalkCorruption2DayInt = -9999>>
<<set $NPCLandladyTalkCorruptionSend2 = false>>
<<set $NPCLandladyCorruptionTalklvl2 = false>>
<<set $NPCLandladyTalkCorruption3DayInt = -9999>>
<<set $NPCLandladyTalkCorruptionSend3 = false>>
<<set $NPCLandladyCorruptionTalklvl3 = false>>
<<set $NPCLandladyChapter5 = false>>
<<set $SedativesBought = false>>
<<set $NPCLandladyTalkCorruption5DayInt = -9999>>
<<set $NPCLandladyTalkCorruptionSend5 = false>>
<<set $SedativesDeliveredWaiting = false>>
<<set $LandladyChapter6Story2Played = false>>
<<set $SedativesDelivered = false>>
<<set $LandladyChapter6Story3Played = false>>
<<set $SedativesGlassWater = false>>
<<set $LandladyChapter6Story4Played = false>>
<<set $NPCLandlordSleepDrug = false>>
/* --- NPCBestFriend SMS --- */
<<set $NPCBestFriendSMSTalklvl2DayInt = -9999>>
<<set $NPCBestFriendSMSSend2 = false>>
<<set $NPCBestFriendSMSTalklvl2 = false>>
/* --- NPCPrincipal Mail & SMS --- */
<<set $NPCPrincipalMailTalklvl0DayInt = -9999>>
<<set $UniversitySummonsMail = false>>
<<set $NPCPrincipalMailSend0 = false>>
<<set $NPCPrincipalSMSTalklvl3DayInt = -9999>>
<<set $NPCPrincipalSMSSend3 = false>>
<<set $NPCPrincipalSMSTalklvl3 = false>>
<<set $PrincipalSummonsLvl3 = false>>
<<set $NPCPrincipalSMSTalklvl5DayInt = -9999>>
<<set $NPCPrincipalSMSSend5 = false>>
<<set $NPCPrincipalSMSTalklvl5 = false>>
<<set $NPCPrincipalSMSTalklvl6DayInt = -9999>>
<<set $NPCPrincipalSMSSend6 = false>>
<<set $NPCPrincipalSMSTalklvl6 = false>>
<<set $PrincipalChapter6End = false>>
/* --- NPCMayor SMS --- */
<<set $NPCMayorSMSTalklvl1DayInt = -9999>>
<<set $NPCMayorSMSTalklvl1 = false>>
<<set $NPCMayorSMSTalklvl2DayInt = -9999>>
<<set $NPCMayorSMSTalklvl2 = false>>
<<set $NPCMayorSMSTalklvl5DayInt = -9999>>
<<set $NPCMayorSMSTalklvl5 = false>>
<<set $NPCMayorSMSSend1= false>>
<<set $NPCMayorSMSSend2 = false>>
<<set $NPCMayorSMSSend5 = false>>
/* --- NPCMate3 SMS --- */
<<set $NPCMate3SMSTalklvl5DayInt = -9999>>
<<set $NPCMate3SMSSend5 = false>>
<<set $NPCMate3SMSTalklvl5 = false>>
/* --- ALL NPC --- */
<<set $NPCList = ["HousemateFemale","HousemateMale","Landlady","Landlord","OnlineFriend","LeftNeighbor","RightNeighbor","BestFriend","Mate1","Mate2","Mate3","TeachSport","TeachTech","TeachLang","Principal","BossGym","BossMarket","Mayor","Homeless","SexShop"]>>
<<set $MCPlayer = {
firstname: "",
lastname: "",
img: "assets/img/character/you.jpg",
color: "#797979", /* light grey */
}>>
<<set $NPCRandom = {
color: "#292929", /* dark grey */
}>>
/* Home */
<<set $NPCHousemateFemale = {
id: "HousemateFemale",
sex: "F",
aff: 0,
cor: 0,
lastCorruptDay: -9,
lastCorruptBool: false,
lvl: 0,
talklvl: 0,
replaytalk: false,
mind: 50,
name: "Kytana",
role: "Housemate",
met: false,
img: "assets/img/character/housematefemale/avatar.jpg",
color: "#ff4da6", /* bright pink */
preg: false,
}>>
<<set $NPCHousemateMale = { /* If futa path is Mary */
id: "HousemateMale",
sex: "M",
aff: 0,
cor: 0,
lastCorruptDay: -9,
lastCorruptBool: false,
lvl: 0,
talklvl: 0,
replaytalk: false,
mind: 75,
name: "Mark",
role: "Housemate",
met: false,
img: "assets/img/character/housematemale/avatar.jpg",
color: "#3399ff", /* light blue */
trans: false,
futa: false,
preg: false,
}>>
<<set $NPCLandlady = {
id: "Landlady",
sex: "F",
aff: 0,
cor: 0,
lastCorruptDay: -9,
lastCorruptBool: false,
lvl: 0,
talklvl: 0,
replaytalk: false,
mind: 100,
name: "Cassandra",
role: "Landlady",
met: false,
img: "assets/img/character/landlady/avatar.jpg",
color: "#ff944d", /* soft orange */
preg: false,
}>>
<<set $NPCLandlord = { /* If futa path is Olivia */
id: "Landlord",
sex: "M",
aff: 0,
cor: 0,
lastCorruptDay: -9,
lastCorruptBool: false,
lvl: 0,
talklvl: 0,
replaytalk: false,
mind: 150,
name: "Oliver",
role: "Landlord",
met: false,
img: "assets/img/character/landlord/avatar.jpg",
color: "#9966ff", /* purple */
trans: false,
futa: false,
preg: false,
}>>
/* Online */
<<set $NPCOnlineFriend = {
id: "OnlineFriend",
sex: "F",
aff: 0,
cor: 0,
lastCorruptDay: -9,
lastCorruptBool: false,
lvl: 0,
talklvl: 0,
replaytalk: false,
mind: 75,
name: "Elyana",
role: "Online Friend",
met: false,
img: "assets/img/character/onlinefriend/avatar.jpg",
color: "#66cc66", /* light green */
house: false,
afk: true,
preg: false,
}>>
/* Neighborhood */
<<set $NPCLeftNeighbor = {
id: "LeftNeighbor",
sex: "F",
aff: 0,
cor: 0,
lastCorruptDay: -9,
lastCorruptBool: false,
lvl: 0,
talklvl: 0,
replaytalk: false,
mind: 150,
name: "Carla",
role: "Left Neighbor",
met: false,
img: "assets/img/character/rightneighbor/avatar.jpg",
color: "#ffcc00", /* bright yellow */
house: false,
athome: false,
preg: false,
}>>
<<set $NPCRightNeighbor = { /* If futa path is Linda */
id: "RightNeighbor",
sex: "M",
aff: 0,
cor: 0,
lastCorruptDay: -9,
lastCorruptBool: false,
lvl: 0,
talklvl: 0,
replaytalk: false,
mind: 150,
name: "Liam",
role: "Right Neighbor",
met: false,
img: "assets/img/character/leftneighbor/avatar.jpg",
color: "#00cccc", /* turquoise */
trans: false,
futa: false,
house: false,
athome: false,
preg: false,
}>>
/* College */
<<set $NPCBestFriend = {
id: "BestFriend",
sex: "F",
aff: 0,
cor: 0,
lastCorruptDay: -9,
lastCorruptBool: false,
lvl: 0,
talklvl: 0,
replaytalk: false,
mind: 75,
name: "Amy",
role: "Bestfriend",
met: false,
img: "assets/img/character/bestfriend/avatar.jpg",
color: "#ff6699", /* soft pink */
house: false,
preg: false,
}>>
<<set $NPCMate1 = {
id: "Mate1",
sex: "F",
aff: 0,
cor: 0,
lastCorruptDay: -9,
lastCorruptBool: false,
lvl: 0,
talklvl: 0,
replaytalk: false,
mind: 150,
name: "April",
role: "Classmate",
met: false,
img: "assets/img/character/mate1/avatar.jpg",
color: "#66ffcc", /* mint green */
preg: false,
}>>
<<set $NPCMate2 = {
id: "Mate2",
sex: "F",
aff: 0,
cor: 0,
lastCorruptDay: -9,
lastCorruptBool: false,
lvl: 0,
talklvl: 0,
replaytalk: false,
mind: 100,
name: "Cecily",
role: "Classmate",
met: false,
img: "assets/img/character/mate2/avatar.jpg",
color: "#ff6666", /* light red */
preg: false,
}>>
<<set $NPCMate3 = {
id: "Mate3",
sex: "F",
aff: 0,
cor: 0,
lastCorruptDay: -9,
lastCorruptBool: false,
lvl: 0,
talklvl: 0,
replaytalk: false,
mind: 75,
name: "Harper",
role: "Classmate",
met: false,
img: "assets/img/character/mate3/avatar.jpg",
color: "#339966", /* dark green */
preg: false,
}>>
<<set $NPCTeachSport = {
id: "TeachSport",
sex: "F",
aff: 0,
cor: 0,
lastCorruptDay: -9,
lastCorruptBool: false,
lvl: 0,
talklvl: 0,
replaytalk: false,
mind: 150,
name: "Grace",
role: "Sport Teacher",
met: false,
img: "assets/img/character/teachsport/avatar.jpg",
color: "#ffcc66", /* apricot */
house: false,
preg: false,
}>>
<<set $NPCTeachTech = {
id: "TeachTech",
sex: "F",
aff: 0,
cor: 0,
lastCorruptDay: -9,
lastCorruptBool: false,
lvl: 0,
talklvl: 0,
replaytalk: false,
mind: 200,
name: "Betty",
role: "Tech Teacher",
met: false,
img: "assets/img/character/teachtech/avatar.jpg",
color: "#0099cc", /* petrol blue */
house: false,
preg: false,
}>>
<<set $NPCTeachLang = {
id: "TeachLang",
sex: "F",
aff: 0,
cor: 0,
lastCorruptDay: -9,
lastCorruptBool: false,
lvl: 0,
talklvl: 0,
replaytalk: false,
mind: 150,
name: "Emma",
role: "Language Teacher",
met: false,
img: "assets/img/character/teachlang/avatar.jpg",
color: "#cc33ff", /* electric violet */
house: false,
preg: false,
}>>
<<set $NPCPrincipal = {
id: "Principal",
sex: "F",
aff: 0,
cor: 0,
lastCorruptDay: -9,
lastCorruptBool: false,
lvl: 0,
talklvl: 0,
replaytalk: false,
mind: 250,
name: "Madison",
role: "Principal",
met: false,
img: "assets/img/character/principal/avatar.jpg",
color: "#8B5CF6", /* bright purple */
house: false,
preg: false,
}>>
/* Mall */
<<set $NPCBossGym = {
id: "BossGym",
sex: "F",
aff: 0,
cor: 0,
lastCorruptDay: -9,
lastCorruptBool: false,
lvl: 0,
talklvl: 0,
replaytalk: false,
mind: 200,
name: "Fiona",
role: "Gym Manager",
met: false,
img: "assets/img/character/bossgym/avatar.jpg",
color: "#ff5050", /* bright red */
preg: false,
}>>
<<set $NPCBossMarket = {
id: "BossMarket",
sex: "F",
aff: 0,
cor: 0,
lastCorruptDay: -9,
lastCorruptBool: false,
lvl: 0,
talklvl: 0,
replaytalk: false,
mind: 200,
name: "Jade",
role: "SuperMarket Manager",
met: false,
img: "assets/img/character/bossmarket/avatar.jpg",
color: "#33cc33", /* vivid green */
preg: false,
}>>
/* CityHall */
<<set $NPCMayor = {
id: "Mayor",
sex: "F",
aff: 0,
cor: 0,
lastCorruptDay: -9,
lastCorruptBool: false,
lvl: 0,
talklvl: 0,
replaytalk: false,
mind: 250,
name: "Lucy",
role: "Mayor",
met: false,
img: "assets/img/character/mayor/avatar.jpg",
color: "#ff9933", /* dark orange */
preg: false,
}>>
/* Old Town */
<<set $NPCHomeless = {
id: "Homeless",
sex: "F",
aff: 0,
cor: 0,
lastCorruptDay: -9,
lastCorruptBool: false,
lvl: 0,
talklvl: 0,
replaytalk: false,
mind: 150,
name: "Lily",
role: "Homeless",
met: false,
img: "assets/img/character/homeless/avatar.jpg",
color: "#66cccc", /* light teal */
slave: false,
preg: false,
}>>
/* Redlight */
<<set $NPCSexShop = {
id: "Sexshop",
sex: "F",
aff: 0,
cor: 0,
lastCorruptDay: -9,
lastCorruptBool: false,
lvl: 0,
talklvl: 0,
replaytalk: false,
mind: 300,
name: "Mia",
role: "SexShop Manager",
met: false,
img: "assets/img/character/sexshop/avatar.jpg",
color: "#ff33cc", /* neon pink */
business: false,
preg: false,
}>>
/* ---===[=•=]===--- | SETUP NPC ASSETS | ---===[=•=]===--- */
<<set setup.npcAssets = {
/* ---=== | HousemateFemale | ===--- */
HousemateFemale: {
lvl0: {
gifs: [
"assets/img/character/housematefemale/lvl0/01.jpg",
"assets/img/character/housematefemale/lvl0/02.jpg",
"assets/img/character/housematefemale/lvl0/03.webp"
],
texts: [
"Yes?",
"Do you want to talk to me?",
]
},
lvl1: {
gifs: [
"assets/img/character/housematefemale/lvl1/01.jpg",
"assets/img/character/housematefemale/lvl1/02.jpg",
"assets/img/character/housematefemale/lvl1/03.jpg"
],
texts: [
"Yes?",
"Do you want to talk to me?",
]
},
lvl2: {
gifs: [
"assets/img/character/housematefemale/lvl2/01.jpg",
"assets/img/character/housematefemale/lvl2/02.jpg",
"assets/img/character/housematefemale/lvl2/03.jpg"
],
texts: [
"Are you okay?",
"Did you want to see me?"
]
},
lvl3: {
gifs: [
"assets/img/character/housematefemale/lvl3/01.jpg",
"assets/img/character/housematefemale/lvl3/02.jpg",
"assets/img/character/housematefemale/lvl3/03.jpg"
],
texts: [
"Yes, my dear?",
"Do you need help?",
]
},
lvl4: {
gifs: [
"assets/img/character/housematefemale/lvl4/01.jpg",
"assets/img/character/housematefemale/lvl4/02.jpg",
"assets/img/character/housematefemale/lvl4/03.jpg"
],
texts: [
"Yes, my love?",
"How can I help you?"
]
},
lvl5: {
gifs: [
"assets/img/character/housematefemale/lvl5/01.jpg",
"assets/img/character/housematefemale/lvl5/02.jpg",
"assets/img/character/housematefemale/lvl5/03.jpg",
"assets/img/character/housematefemale/lvl5/04.webp",
"assets/img/character/housematefemale/lvl5/05.webp"
],
texts: [
"Yes, master?",
"How can I help you?"
]
},
},
/* ---=== | HousemateMale | ===--- */
HousemateMale: {
lvl0: {
gifs: [
"assets/img/character/housematemale/lvl0/01.gif",
"assets/img/character/housematemale/lvl0/02.gif",
"assets/img/character/housematemale/lvl0/03.gif"
],
texts: [
"Yes?",
"Do you want to talk to me?",
]
},
lvl1: {
gifs: [
"assets/img/character/housematemale/lvl1/01.gif",
"assets/img/character/housematemale/lvl1/02.gif",
"assets/img/character/housematemale/lvl1/03.gif"
],
texts: [
"Yes?",
"Do you want to talk to me?",
]
},
lvl2: {
gifs: [
"assets/img/character/housematemale/lvl2/01.gif",
"assets/img/character/housematemale/lvl2/02.gif"
],
texts: [
"Are you okay?",
"Did you want to see me?"
]
},
lvl3: {
gifs: [
"assets/img/character/housematemale/lvl3/01.gif",
"assets/img/character/housematemale/lvl3/02.gif",
"assets/img/character/housematemale/lvl3/03.gif"
],
texts: [
"Yes, my dear?",
"Do you need help?",
]
},
lvl4: {
gifs: [
"assets/img/character/housematemale/lvl4/01.gif",
"assets/img/character/housematemale/lvl4/02.gif"
],
texts: [
"Yes, my love?",
"How can I help you?"
]
},
lvl5: {
gifs: [
"assets/img/character/housematemale/lvl5/01.gif",
"assets/img/character/housematemale/lvl5/02.gif"
],
texts: [
"Yes, master?",
"How can I help you?"
]
},
},
/* ---=== | Landlady | ===--- */
Landlady: {
lvl0: {
gifs: [
"assets/img/character/landlady/lvl0/01.jpg",
"assets/img/character/landlady/lvl0/02.jpg",
"assets/img/character/landlady/lvl0/03.jpg"
],
texts: [
"Yes?",
"Do you want to talk to me?",
]
},
lvl1: {
gifs: [
"assets/img/character/landlady/lvl1/01.jpg",
"assets/img/character/landlady/lvl1/02.jpg",
"assets/img/character/landlady/lvl1/03.jpg"
],
texts: [
"Yes?",
"Do you want to talk to me?",
]
},
lvl2: {
gifs: [
"assets/img/character/landlady/lvl2/01.jpg",
"assets/img/character/landlady/lvl2/02.jpg",
"assets/img/character/landlady/lvl2/03.jpg"
],
texts: [
"Are you okay?",
"Did you want to see me?"
]
},
lvl3: {
gifs: [
"assets/img/character/landlady/lvl3/01.jpg",
"assets/img/character/landlady/lvl3/02.jpg",
"assets/img/character/landlady/lvl3/03.jpg",
"assets/img/character/landlady/lvl3/04.jpg"
],
texts: [
"Yes, my dear?",
"Do you need help?",
]
},
lvl4: {
gifs: [
"assets/img/character/landlady/lvl4/01.jpg",
"assets/img/character/landlady/lvl4/02.jpg",
"assets/img/character/landlady/lvl4/03.jpg"
],
texts: [
"Yes, my master?",
"How can I help you?"
]
},
lvl5: {
gifs: [
"assets/img/character/landlady/lvl5/01.jpg",
"assets/img/character/landlady/lvl5/02.jpg",
"assets/img/character/landlady/lvl5/03.jpg",
"assets/img/character/landlady/lvl5/04.jpg",
"assets/img/character/landlady/lvl5/05.jpg",
"assets/img/character/landlady/lvl5/06.webp",
"assets/img/character/landlady/lvl5/07.webp",
"assets/img/character/landlady/lvl5/08.webp",
"assets/img/character/landlady/lvl5/09.webp"
],
texts: [
"Yes, master?",
"How can I help you?"
]
},
},
/* ---=== | Landlord | ===--- */
Landlord: {
lvl0: {
gifs: [
"assets/img/character/landlord/lvl0/01.gif",
"assets/img/character/landlord/lvl0/02.gif",
"assets/img/character/landlord/lvl0/03.gif"
],
texts: [
"Yes?",
"Do you want to talk to me?",
]
},
lvl1: {
gifs: [
"assets/img/character/landlord/lvl1/01.gif",
"assets/img/character/landlord/lvl1/02.gif",
"assets/img/character/landlord/lvl1/03.gif"
],
texts: [
"Yes?",
"Do you want to talk to me?",
]
},
lvl2: {
gifs: [
"assets/img/character/landlord/lvl2/01.gif",
"assets/img/character/landlord/lvl2/02.gif"
],
texts: [
"Are you okay?",
"Did you want to see me?"
]
},
lvl3: {
gifs: [
"assets/img/character/landlord/lvl3/01.gif",
"assets/img/character/landlord/lvl3/02.gif",
"assets/img/character/landlord/lvl3/03.gif"
],
texts: [
"Yes, my dear?",
"Do you need help?",
]
},
lvl4: {
gifs: [
"assets/img/character/landlord/lvl4/01.gif",
"assets/img/character/landlord/lvl4/02.gif"
],
texts: [
"Yes, my love?",
"How can I help you?"
]
},
lvl5: {
gifs: [
"assets/img/character/landlord/lvl5/01.gif",
"assets/img/character/landlord/lvl5/02.gif"
],
texts: [
"Yes, master?",
"How can I help you?"
]
},
},
/* ---=== | ONLINE FRIEND | ===--- */
OnlineFriend: {
lvl0: {
gifs: [
"assets/img/character/onlinefriend/lvl0/01.gif",
"assets/img/character/onlinefriend/lvl0/02.gif",
"assets/img/character/onlinefriend/lvl0/03.gif"
],
texts: [
"Yes?",
"Do you want to talk to me?",
]
},
lvl1: {
gifs: [
"assets/img/character/onlinefriend/lvl1/01.gif",
"assets/img/character/onlinefriend/lvl1/02.gif",
"assets/img/character/onlinefriend/lvl1/03.gif"
],
texts: [
"Yes?",
"Do you want to talk to me?",
]
},
lvl2: {
gifs: [
"assets/img/character/onlinefriend/lvl2/01.gif",
"assets/img/character/onlinefriend/lvl2/02.gif"
],
texts: [
"Are you okay?",
"Did you want to see me?"
]
},
lvl3: {
gifs: [
"assets/img/character/onlinefriend/lvl3/01.gif",
"assets/img/character/onlinefriend/lvl3/02.gif",
"assets/img/character/onlinefriend/lvl3/03.gif"
],
texts: [
"Yes, my dear?",
"Do you need help?",
]
},
lvl4: {
gifs: [
"assets/img/character/onlinefriend/lvl4/01.gif",
"assets/img/character/onlinefriend/lvl4/02.gif"
],
texts: [
"Yes, my love?",
"How can I help you?"
]
},
lvl5: {
gifs: [
"assets/img/character/onlinefriend/lvl5/01.gif",
"assets/img/character/onlinefriend/lvl5/02.gif"
],
texts: [
"Yes, master?",
"How can I help you?"
]
},
},
/* ---=== | LEFT NEIGHBOR | ===--- */
LeftNeighbor: {
lvl0: {
gifs: [
"assets/img/character/leftneighbor/lvl0/01.gif",
"assets/img/character/leftneighbor/lvl0/02.gif",
"assets/img/character/leftneighbor/lvl0/03.gif"
],
texts: [
"Yes?",
"Do you want to talk to me?",
]
},
lvl1: {
gifs: [
"assets/img/character/leftneighbor/lvl1/01.gif",
"assets/img/character/leftneighbor/lvl1/02.gif",
"assets/img/character/leftneighbor/lvl1/03.gif"
],
texts: [
"Yes?",
"Do you want to talk to me?",
]
},
lvl2: {
gifs: [
"assets/img/character/leftneighbor/lvl2/01.gif",
"assets/img/character/leftneighbor/lvl2/02.gif"
],
texts: [
"Are you okay?",
"Did you want to see me?"
]
},
lvl3: {
gifs: [
"assets/img/character/leftneighbor/lvl3/01.gif",
"assets/img/character/leftneighbor/lvl3/02.gif",
"assets/img/character/leftneighbor/lvl3/03.gif"
],
texts: [
"Yes, my dear?",
"Do you need help?",
]
},
lvl4: {
gifs: [
"assets/img/character/leftneighbor/lvl4/01.gif",
"assets/img/character/leftneighbor/lvl4/02.gif"
],
texts: [
"Yes, my love?",
"How can I help you?"
]
},
lvl5: {
gifs: [
"assets/img/character/leftneighbor/lvl5/01.gif",
"assets/img/character/leftneighbor/lvl5/02.gif"
],
texts: [
"Yes, master?",
"How can I help you?"
]
},
},
/* ---=== | RIGHT NEIGHBOR | ===--- */
RightNeighbor: {
lvl0: {
gifs: [
"assets/img/character/rightneighbor/lvl0/01.gif",
"assets/img/character/rightneighbor/lvl0/02.gif",
"assets/img/character/rightneighbor/lvl0/03.gif"
],
texts: [
"Yes?",
"Do you want to talk to me?",
]
},
lvl1: {
gifs: [
"assets/img/character/rightneighbor/lvl1/01.gif",
"assets/img/character/rightneighbor/lvl1/02.gif",
"assets/img/character/rightneighbor/lvl1/03.gif"
],
texts: [
"Yes?",
"Do you want to talk to me?",
]
},
lvl2: {
gifs: [
"assets/img/character/rightneighbor/lvl2/01.gif",
"assets/img/character/rightneighbor/lvl2/02.gif"
],
texts: [
"Are you okay?",
"Did you want to see me?"
]
},
lvl3: {
gifs: [
"assets/img/character/rightneighbor/lvl3/01.gif",
"assets/img/character/rightneighbor/lvl3/02.gif",
"assets/img/character/rightneighbor/lvl3/03.gif"
],
texts: [
"Yes, my dear?",
"Do you need help?",
]
},
lvl4: {
gifs: [
"assets/img/character/rightneighbor/lvl4/01.gif",
"assets/img/character/rightneighbor/lvl4/02.gif"
],
texts: [
"Yes, my love?",
"How can I help you?"
]
},
lvl5: {
gifs: [
"assets/img/character/rightneighbor/lvl5/01.gif",
"assets/img/character/rightneighbor/lvl5/02.gif"
],
texts: [
"Yes, master?",
"How can I help you?"
]
},
},
/* ---=== | BEST FRIEND | ===--- */
BestFriend: {
lvl0: {
gifs: [
"assets/img/character/bestfriend/lvl0/01.jpg",
"assets/img/character/bestfriend/lvl0/02.jpg",
"assets/img/character/bestfriend/lvl0/03.jpg"
],
texts: [
"Yes?",
"Do you want to talk to me?",
]
},
lvl1: {
gifs: [
"assets/img/character/bestfriend/lvl1/01.jpg",
"assets/img/character/bestfriend/lvl1/02.jpg",
"assets/img/character/bestfriend/lvl1/03.jpg"
],
texts: [
"Yes?",
"Do you want to talk to me?",
]
},
lvl2: {
gifs: [
"assets/img/character/bestfriend/lvl2/01.jpg",
"assets/img/character/bestfriend/lvl2/02.jpg",
"assets/img/character/bestfriend/lvl2/03.jpg"
],
texts: [
"Are you okay?",
"Did you want to see me?"
]
},
lvl3: {
gifs: [
"assets/img/character/bestfriend/lvl3/01.jpg",
"assets/img/character/bestfriend/lvl3/02.jpg",
"assets/img/character/bestfriend/lvl3/03.jpg"
],
texts: [
"Yes, my dear?",
"Do you need help?",
]
},
lvl4: {
gifs: [
"assets/img/character/bestfriend/lvl4/01.jpg",
"assets/img/character/bestfriend/lvl4/02.jpg",
"assets/img/character/bestfriend/lvl4/03.jpg"
],
texts: [
"Yes, my love?",
"How can I help you?"
]
},
lvl5: {
gifs: [
"assets/img/character/bestfriend/lvl5/01.jpg",
"assets/img/character/bestfriend/lvl5/02.jpg",
"assets/img/character/bestfriend/lvl5/03.jpg",
"assets/img/character/bestfriend/lvl5/04.webp",
"assets/img/character/bestfriend/lvl5/05.webp",
"assets/img/character/bestfriend/lvl5/06.webp",
"assets/img/character/bestfriend/lvl5/07.webp"
],
texts: [
"Yes, master?",
"How can I help you?"
]
},
},
/* ---=== | CLASSMATE 1 | ===--- */
Mate1: {
lvl0: {
gifs: [
"assets/img/character/mate1/lvl0/01.jpg",
"assets/img/character/mate1/lvl0/02.jpg",
"assets/img/character/mate1/lvl0/03.jpg"
],
texts: [
"Yes?",
"Do you want to talk to me?",
]
},
lvl1: {
gifs: [
"assets/img/character/mate1/lvl1/01.jpg",
"assets/img/character/mate1/lvl1/02.jpg",
"assets/img/character/mate1/lvl1/03.jpg"
],
texts: [
"Yes?",
"Do you want to talk to me?",
]
},
lvl2: {
gifs: [
"assets/img/character/mate1/lvl2/01.jpg",
"assets/img/character/mate1/lvl2/02.jpg",
"assets/img/character/mate1/lvl2/03.jpg"
],
texts: [
"Are you okay?",
"Did you want to see me?"
]
},
lvl3: {
gifs: [
"assets/img/character/mate1/lvl3/01.jpg",
"assets/img/character/mate1/lvl3/02.jpg",
"assets/img/character/mate1/lvl3/03.jpg"
],
texts: [
"Yes, my dear?",
"Do you need help?",
]
},
lvl4: {
gifs: [
"assets/img/character/mate1/lvl4/01.jpg",
"assets/img/character/mate1/lvl4/02.jpg",
"assets/img/character/mate1/lvl4/03.jpg"
],
texts: [
"Yes, my love?",
"How can I help you?"
]
},
lvl5: {
gifs: [
"assets/img/character/mate1/lvl5/01.jpg",
"assets/img/character/mate1/lvl5/02.jpg",
"assets/img/character/mate1/lvl5/03.jpg",
"assets/img/character/mate1/lvl5/04.jpg",
"assets/img/character/mate1/lvl5/05.jpg",
"assets/img/character/mate1/lvl5/06.webp"
],
texts: [
"Yes, master?",
"How can I help you?"
]
},
},
/* ---=== | CLASSMATE 2 | ===--- */
Mate2: {
lvl0: {
gifs: [
"assets/img/character/mate2/lvl0/01.jpg",
"assets/img/character/mate2/lvl0/02.jpg",
"assets/img/character/mate2/lvl0/03.jpg"
],
texts: [
"Yes?",
"Do you want to talk to me?",
]
},
lvl1: {
gifs: [
"assets/img/character/mate2/lvl1/01.jpg",
"assets/img/character/mate2/lvl1/02.jpg",
"assets/img/character/mate2/lvl1/03.jpg"
],
texts: [
"Yes?",
"Do you want to talk to me?",
]
},
lvl2: {
gifs: [
"assets/img/character/mate2/lvl2/01.jpg",
"assets/img/character/mate2/lvl2/02.jpg",
"assets/img/character/mate2/lvl2/03.jpg"
],
texts: [
"Are you okay?",
"Did you want to see me?"
]
},
lvl3: {
gifs: [
"assets/img/character/mate2/lvl3/01.jpg",
"assets/img/character/mate2/lvl3/02.jpg",
"assets/img/character/mate2/lvl3/03.jpg"
],
texts: [
"Yes, my dear?",
"Do you need help?",
]
},
lvl4: {
gifs: [
"assets/img/character/mate2/lvl4/01.jpg",
"assets/img/character/mate2/lvl4/02.jpg",
"assets/img/character/mate2/lvl4/03.jpg"
],
texts: [
"Yes, my love?",
"How can I help you?"
]
},
lvl5: {
gifs: [
"assets/img/character/mate2/lvl5/01.jpg",
"assets/img/character/mate2/lvl5/02.jpg",
"assets/img/character/mate2/lvl5/03.jpg",
"assets/img/character/mate2/lvl5/04.jpg",
"assets/img/character/mate2/lvl5/05.jpg",
"assets/img/character/mate2/lvl5/06.webp",
"assets/img/character/mate2/lvl5/07.webp",
],
texts: [
"Yes, master?",
"How can I help you?"
]
},
},
/* ---=== | CLASSMATE 3 | ===--- */
Mate3: {
lvl0: {
gifs: [
"assets/img/character/mate3/lvl0/01.jpg",
"assets/img/character/mate3/lvl0/02.jpg",
"assets/img/character/mate3/lvl0/03.jpg"
],
texts: [
"Yes?",
"What do you want?",
]
},
lvl1: {
gifs: [
"assets/img/character/mate3/lvl1/01.jpg",
"assets/img/character/mate3/lvl1/02.jpg",
"assets/img/character/mate3/lvl1/03.jpg"
],
texts: [
"Yes?",
"Do you want to talk to me?",
]
},
lvl2: {
gifs: [
"assets/img/character/mate3/lvl2/01.jpg",
"assets/img/character/mate3/lvl2/02.jpg",
"assets/img/character/mate3/lvl2/03.jpg"
],
texts: [
"Are you okay?",
"Did you want to see me?"
]
},
lvl3: {
gifs: [
"assets/img/character/mate3/lvl3/01.jpg",
"assets/img/character/mate3/lvl3/02.jpg",
"assets/img/character/mate3/lvl3/03.jpg"
],
texts: [
"Yes, my dear?",
"Do you need help?",
]
},
lvl4: {
gifs: [
"assets/img/character/mate3/lvl4/01.jpg",
"assets/img/character/mate3/lvl4/02.jpg",
"assets/img/character/mate3/lvl4/03.jpg"
],
texts: [
"Yes, my love?",
"How can I help you?"
]
},
lvl5: {
gifs: [
"assets/img/character/mate3/lvl5/01.jpg",
"assets/img/character/mate3/lvl5/02.jpg",
"assets/img/character/mate3/lvl5/03.jpg",
"assets/img/character/mate3/lvl5/04.jpg",
"assets/img/character/mate3/lvl5/05.webp",
"assets/img/character/mate3/lvl5/06.webp",
"assets/img/character/mate3/lvl5/07.webp"
],
texts: [
"Yes, master?",
"How can I help you?"
]
},
},
/* ---=== | TEACHER SPORT | ===--- */
TeachSport: {
lvl0: {
gifs: [
"assets/img/character/teachsport/lvl0/01.gif",
"assets/img/character/teachsport/lvl0/02.gif",
"assets/img/character/teachsport/lvl0/03.gif"
],
texts: [
"Yes?",
"Do you want to talk to me?",
]
},
lvl1: {
gifs: [
"assets/img/character/teachsport/lvl1/01.gif",
"assets/img/character/teachsport/lvl1/02.gif",
"assets/img/character/teachsport/lvl1/03.gif"
],
texts: [
"Yes?",
"Do you want to talk to me?",
]
},
lvl2: {
gifs: [
"assets/img/character/teachsport/lvl2/01.gif",
"assets/img/character/teachsport/lvl2/02.gif"
],
texts: [
"Are you okay?",
"Did you want to see me?"
]
},
lvl3: {
gifs: [
"assets/img/character/teachsport/lvl3/01.gif",
"assets/img/character/teachsport/lvl3/02.gif",
"assets/img/character/teachsport/lvl3/03.gif"
],
texts: [
"Yes, my dear?",
"Do you need help?",
]
},
lvl4: {
gifs: [
"assets/img/character/teachsport/lvl4/01.gif",
"assets/img/character/teachsport/lvl4/02.gif"
],
texts: [
"Yes, my love?",
"How can I help you?"
]
},
lvl5: {
gifs: [
"assets/img/character/teachsport/lvl5/01.gif",
"assets/img/character/teachsport/lvl5/02.gif"
],
texts: [
"Yes, master?",
"How can I help you?"
]
},
},
/* ---=== | TEACHER TECH | ===--- */
TeachTech: {
lvl0: {
gifs: [
"assets/img/character/teachtech/lvl0/01.gif",
"assets/img/character/teachtech/lvl0/02.gif",
"assets/img/character/teachtech/lvl0/03.gif"
],
texts: [
"Yes?",
"Do you want to talk to me?",
]
},
lvl1: {
gifs: [
"assets/img/character/teachtech/lvl1/01.gif",
"assets/img/character/teachtech/lvl1/02.gif",
"assets/img/character/teachtech/lvl1/03.gif"
],
texts: [
"Yes?",
"Do you want to talk to me?",
]
},
lvl2: {
gifs: [
"assets/img/character/teachtech/lvl2/01.gif",
"assets/img/character/teachtech/lvl2/02.gif"
],
texts: [
"Are you okay?",
"Did you want to see me?"
]
},
lvl3: {
gifs: [
"assets/img/character/teachtech/lvl3/01.gif",
"assets/img/character/teachtech/lvl3/02.gif",
"assets/img/character/teachtech/lvl3/03.gif"
],
texts: [
"Yes, my dear?",
"Do you need help?",
]
},
lvl4: {
gifs: [
"assets/img/character/teachtech/lvl4/01.gif",
"assets/img/character/teachtech/lvl4/02.gif"
],
texts: [
"Yes, my love?",
"How can I help you?"
]
},
lvl5: {
gifs: [
"assets/img/character/teachtech/lvl5/01.gif",
"assets/img/character/teachtech/lvl5/02.gif"
],
texts: [
"Yes, master?",
"How can I help you?"
]
},
},
/* ---=== | TEACHER LANGUAGE | ===--- */
TeachLang: {
lvl0: {
gifs: [
"assets/img/character/teachlang/lvl0/01.gif",
"assets/img/character/teachlang/lvl0/02.gif",
"assets/img/character/teachlang/lvl0/03.gif"
],
texts: [
"Yes?",
"Do you want to talk to me?",
]
},
lvl1: {
gifs: [
"assets/img/character/teachlang/lvl1/01.gif",
"assets/img/character/teachlang/lvl1/02.gif",
"assets/img/character/teachlang/lvl1/03.gif"
],
texts: [
"Yes?",
"Do you want to talk to me?",
]
},
lvl2: {
gifs: [
"assets/img/character/teachlang/lvl2/01.gif",
"assets/img/character/teachlang/lvl2/02.gif"
],
texts: [
"Are you okay?",
"Did you want to see me?"
]
},
lvl3: {
gifs: [
"assets/img/character/teachlang/lvl3/01.gif",
"assets/img/character/teachlang/lvl3/02.gif",
"assets/img/character/teachlang/lvl3/03.gif"
],
texts: [
"Yes, my dear?",
"Do you need help?",
]
},
lvl4: {
gifs: [
"assets/img/character/teachlang/lvl4/01.gif",
"assets/img/character/teachlang/lvl4/02.gif"
],
texts: [
"Yes, my love?",
"How can I help you?"
]
},
lvl5: {
gifs: [
"assets/img/character/teachlang/lvl5/01.gif",
"assets/img/character/teachlang/lvl5/02.gif"
],
texts: [
"Yes, master?",
"How can I help you?"
]
},
},
/* ---=== | PRINCIPAL | ===--- */
Principal: {
lvl0: {
gifs: [
"assets/img/character/principal/lvl0/01.jpg",
"assets/img/character/principal/lvl0/02.jpg",
"assets/img/character/principal/lvl0/03.jpg"
],
texts: [
"Yes?",
"Do you want to talk to me?",
]
},
lvl1: {
gifs: [
"assets/img/character/principal/lvl1/01.jpg",
"assets/img/character/principal/lvl1/02.jpg",
"assets/img/character/principal/lvl1/03.jpg"
],
texts: [
"Yes?",
"Do you want to talk to me?",
]
},
lvl2: {
gifs: [
"assets/img/character/principal/lvl2/01.jpg",
"assets/img/character/principal/lvl2/02.jpg",
"assets/img/character/principal/lvl2/03.jpg"
],
texts: [
"Are you okay?",
"Did you want to see me?"
]
},
lvl3: {
gifs: [
"assets/img/character/principal/lvl3/01.jpg",
"assets/img/character/principal/lvl3/02.jpg",
"assets/img/character/principal/lvl3/03.jpg"
],
texts: [
"Yes, my dear?",
"Do you need help?",
]
},
lvl4: {
gifs: [
"assets/img/character/principal/lvl4/01.jpg",
"assets/img/character/principal/lvl4/02.jpg",
"assets/img/character/principal/lvl4/03.jpg"
],
texts: [
"Yes, my love?",
"How can I help you?"
]
},
lvl5: {
gifs: [
"assets/img/character/principal/lvl5/01.jpg",
"assets/img/character/principal/lvl5/02.jpg",
"assets/img/character/principal/lvl5/03.jpg",
"assets/img/character/principal/lvl5/04.jpg",
"assets/img/character/principal/lvl5/05.jpg"
],
texts: [
"Yes, master?",
"How can I help you?"
]
},
},
/* ---=== | BOSS GYM | ===--- */
BossGym: {
lvl0: {
gifs: [
"assets/img/character/bossgym/lvl0/01.gif",
"assets/img/character/bossgym/lvl0/02.gif",
"assets/img/character/bossgym/lvl0/03.gif"
],
texts: [
"Yes?",
"Do you want to talk to me?",
]
},
lvl1: {
gifs: [
"assets/img/character/bossgym/lvl1/01.gif",
"assets/img/character/bossgym/lvl1/02.gif",
"assets/img/character/bossgym/lvl1/03.gif"
],
texts: [
"Yes?",
"Do you want to talk to me?",
]
},
lvl2: {
gifs: [
"assets/img/character/bossgym/lvl2/01.gif",
"assets/img/character/bossgym/lvl2/02.gif"
],
texts: [
"Are you okay?",
"Did you want to see me?"
]
},
lvl3: {
gifs: [
"assets/img/character/bossgym/lvl3/01.gif",
"assets/img/character/bossgym/lvl3/02.gif",
"assets/img/character/bossgym/lvl3/03.gif"
],
texts: [
"Yes, my dear?",
"Do you need help?",
]
},
lvl4: {
gifs: [
"assets/img/character/bossgym/lvl4/01.gif",
"assets/img/character/bossgym/lvl4/02.gif"
],
texts: [
"Yes, my love?",
"How can I help you?"
]
},
lvl5: {
gifs: [
"assets/img/character/bossgym/lvl5/01.gif",
"assets/img/character/bossgym/lvl5/02.gif"
],
texts: [
"Yes, master?",
"How can I help you?"
]
},
},
/* ---=== | BOSS MARKET | ===--- */
BossMarket: {
lvl0: {
gifs: [
"assets/img/character/bossmarket/lvl0/01.gif",
"assets/img/character/bossmarket/lvl0/02.gif",
"assets/img/character/bossmarket/lvl0/03.gif"
],
texts: [
"Yes?",
"Do you want to talk to me?",
]
},
lvl1: {
gifs: [
"assets/img/character/bossmarket/lvl1/01.gif",
"assets/img/character/bossmarket/lvl1/02.gif",
"assets/img/character/bossmarket/lvl1/03.gif"
],
texts: [
"Yes?",
"Do you want to talk to me?",
]
},
lvl2: {
gifs: [
"assets/img/character/bossmarket/lvl2/01.gif",
"assets/img/character/bossmarket/lvl2/02.gif"
],
texts: [
"Are you okay?",
"Did you want to see me?"
]
},
lvl3: {
gifs: [
"assets/img/character/bossmarket/lvl3/01.gif",
"assets/img/character/bossmarket/lvl3/02.gif",
"assets/img/character/bossmarket/lvl3/03.gif"
],
texts: [
"Yes, my dear?",
"Do you need help?",
]
},
lvl4: {
gifs: [
"assets/img/character/bossmarket/lvl4/01.gif",
"assets/img/character/bossmarket/lvl4/02.gif"
],
texts: [
"Yes, my love?",
"How can I help you?"
]
},
lvl5: {
gifs: [
"assets/img/character/bossmarket/lvl5/01.gif",
"assets/img/character/bossmarket/lvl5/02.gif"
],
texts: [
"Yes, master?",
"How can I help you?"
]
},
},
/* ---=== | MAYOR | ===--- */
Mayor: {
lvl0: {
gifs: [
"assets/img/character/mayor/lvl0/01.jpg",
"assets/img/character/mayor/lvl0/02.jpg",
"assets/img/character/mayor/lvl0/03.jpg"
],
texts: [
"Yes?",
"Who are you?",
]
},
lvl1: {
gifs: [
"assets/img/character/mayor/lvl1/01.jpg",
"assets/img/character/mayor/lvl1/02.jpg",
"assets/img/character/mayor/lvl1/03.jpg"
],
texts: [
"Yes?",
"Do you want to talk to me?",
]
},
lvl2: {
gifs: [
"assets/img/character/mayor/lvl2/01.jpg",
"assets/img/character/mayor/lvl2/02.jpg",
"assets/img/character/mayor/lvl2/03.jpg"
],
texts: [
"Are you okay?",
"Did you want to see me?"
]
},
lvl3: {
gifs: [
"assets/img/character/mayor/lvl3/01.jpg",
"assets/img/character/mayor/lvl3/02.jpg",
"assets/img/character/mayor/lvl3/03.jpg"
],
texts: [
"Yes, my dear?",
"Do you need help?",
]
},
lvl4: {
gifs: [
"assets/img/character/mayor/lvl4/01.jpg",
"assets/img/character/mayor/lvl4/02.jpg",
"assets/img/character/mayor/lvl4/03.jpg"
],
texts: [
"Yes, my love?",
"How can I help you?"
]
},
lvl5: {
gifs: [
"assets/img/character/mayor/lvl5/01.jpg",
"assets/img/character/mayor/lvl5/02.jpg",
"assets/img/character/mayor/lvl5/03.jpg",
"assets/img/character/mayor/lvl5/04.jpg",
"assets/img/character/mayor/lvl5/05.jpg",
"assets/img/character/mayor/lvl5/06.webp",
"assets/img/character/mayor/lvl5/07.webp"
],
texts: [
"Yes, master?",
"How can I help you?"
]
},
},
/* ---=== | HOMELESS | ===--- */
Homeless: {
lvl0: {
gifs: [
"assets/img/character/homeless/lvl0/01.gif",
"assets/img/character/homeless/lvl0/02.gif",
"assets/img/character/homeless/lvl0/03.gif"
],
texts: [
"Yes?",
"Do you want to talk to me?",
]
},
lvl1: {
gifs: [
"assets/img/character/homeless/lvl1/01.gif",
"assets/img/character/homeless/lvl1/02.gif",
"assets/img/character/homeless/lvl1/03.gif"
],
texts: [
"Yes?",
"Do you want to talk to me?",
]
},
lvl2: {
gifs: [
"assets/img/character/homeless/lvl2/01.gif",
"assets/img/character/homeless/lvl2/02.gif"
],
texts: [
"Are you okay?",
"Did you want to see me?"
]
},
lvl3: {
gifs: [
"assets/img/character/homeless/lvl3/01.gif",
"assets/img/character/homeless/lvl3/02.gif",
"assets/img/character/homeless/lvl3/03.gif"
],
texts: [
"Yes, my dear?",
"Do you need help?",
]
},
lvl4: {
gifs: [
"assets/img/character/homeless/lvl4/01.gif",
"assets/img/character/homeless/lvl4/02.gif"
],
texts: [
"Yes, my love?",
"How can I help you?"
]
},
lvl5: {
gifs: [
"assets/img/character/homeless/lvl5/01.gif",
"assets/img/character/homeless/lvl5/02.gif"
],
texts: [
"Yes, master?",
"How can I help you?"
]
},
},
/* ---=== | BOSS SEXSHOP | ===--- */
Sexshop: {
lvl0: {
gifs: [
"assets/img/character/sexshop/lvl0/01.gif",
"assets/img/character/sexshop/lvl0/02.gif",
"assets/img/character/sexshop/lvl0/03.gif"
],
texts: [
"Yes?",
"Do you want to talk to me?",
]
},
lvl1: {
gifs: [
"assets/img/character/sexshop/lvl1/01.gif",
"assets/img/character/sexshop/lvl1/02.gif",
"assets/img/character/sexshop/lvl1/03.gif"
],
texts: [
"Yes?",
"Do you want to talk to me?",
]
},
lvl2: {
gifs: [
"assets/img/character/sexshop/lvl2/01.gif",
"assets/img/character/sexshop/lvl2/02.gif"
],
texts: [
"Are you okay?",
"Did you want to see me?"
]
},
lvl3: {
gifs: [
"assets/img/character/sexshop/lvl3/01.gif",
"assets/img/character/sexshop/lvl3/02.gif",
"assets/img/character/sexshop/lvl3/03.gif"
],
texts: [
"Yes, my dear?",
"Do you need help?",
]
},
lvl4: {
gifs: [
"assets/img/character/sexshop/lvl4/01.gif",
"assets/img/character/sexshop/lvl4/02.gif"
],
texts: [
"Yes, my love?",
"How can I help you?"
]
},
lvl5: {
gifs: [
"assets/img/character/sexshop/lvl5/01.gif",
"assets/img/character/sexshop/lvl5/02.gif"
],
texts: [
"Yes, master?",
"How can I help you?"
]
},
},
} >>
/* ---===[=•=]===--- | PC COMPONENT | ---===[=•=]===--- */
<<set $PCMotherboard = {
name: "GIGABYTE H510M H V2",
img: 1,
}>>
<<set $PCcpu = {
name: "Intel Core i3-10100 (3.6 GHz)",
img: 1,
}>>
<<set $PCgpu = {
name: "MSI GeForce GT 1030 2GHD4 LP OC",
img: 1,
}>>
<<set $PCram = {
name: "DDR4 Kingston Fury Beast - 8 Go 3200 MHz - CAS 16",
img: 1,
}>>
<<set $PCstockage = {
name: "WD Blue SN570 500GB NVMe",
img: 1,
}>>
<<set $PCos = {
name: "Windows XP",
img: 1,
}>>
<<set $PCscreen = {
name: "HP P223 - 22 inch",
img: 1,
}>>
<<set $PCkeyboard = {
name: "Dell KB216",
img: 1,
}>>
<<set $PCmouse = {
name: "High One MWD01B",
img: 1,
}>>
<<set $PCheadset = {
name: "TnB Arko",
img: 1,
}>>
<<set $PCmicrophone = {
name: "Nothing",
img: 0,
}>>
<<set $PCcamera = {
name: "Nothing",
img: 0,
}>>
/* ---===[=•=]===--- | VIDEO GAMES | ---===[=•=]===--- */
<<set $PlayerCS2 = {
username: "",
age: 18,
xp: {
total: 0,
to_next_level: 500,
by_category: {
firepower: 0, entrying: 0, trading: 0,
opening: 0, clutching: 0, sniping: 0, utility: 0,
weapons: 0, maps: 0
}
},
level: {
current: 1,
skill_points: 0,
spent_points: 0
},
elo: {
current: 800,
peak: 800,
history: []
},
faceit: {
lvl: 1,
xpToNext: 500
},
skills: {
firepower: { val:10, xp:0 },
entrying: { val:10, xp:0 },
trading: { val:10, xp:0 },
opening: { val:10, xp:0 },
clutching: { val:10, xp:0 },
sniping: { val:10, xp:0 },
utility: { val:10, xp:0 }
},
weapons: {
ak47: { val:10, xp:0 },
m4a4: { val:10, xp:0 },
m4a1s: { val:10, xp:0 },
awp: { val:10, xp:0 },
deagle: { val:10, xp:0 },
ssg08: { val:10, xp:0 },
mp9: { val:10, xp:0 },
p90: { val:10, xp:0 }
},
maps: {
de_mirage: { val:10, xp:0 },
de_dust2: { val:10, xp:0 },
de_inferno: { val:10, xp:0 },
de_nuke: { val:10, xp:0 },
de_ancient: { val:10, xp:0 },
de_anubis: { val:10, xp:0 },
de_vertigo: { val:10, xp:0 }
},
utility_mastery: {
smoke: { val:10, xp:0 },
flash: { val:10, xp:0 },
molotov: { val:10, xp:0 },
he: { val:10, xp:0 }
},
role: "entry",
map_pool: ["de_mirage","de_dust2","de_inferno"],
preferred_side: "T",
stats: {
kills:0, deaths:0, assists:0,
rounds_played:0, matches_played:0, matches_won:0,
damage_total:0, opening_kills:0, opening_deaths:0,
clutches_won:0, clutches_total:0, flash_assists:0,
utility_damage:0, sniper_kills:0, trade_kills:0,
saved_teammates:0, first_bloods:0, adr:0, kd:0, rating:0
},
moral: 75,
fatigue: 0,
last_trained: 0,
training_streak: 0,
days_without_training: 0,
refrag_sub: false,
refrag_bonus: 0,
career: {
status: "free",
team_id: null,
contract_end: null,
salary: 0,
buyout: 0,
benched: false,
tryout_pending: false,
fame: 0,
total_earned: 0
},
pc: {
cpu:50, gpu:50, ram:50, hz:144, ping:20
}
}>>
/* ---===[=•=]===--- | WIDGET | ---===[=•=]===--- */
--------------------------------------------------------------------------
<<widget "DrugSell">><<set _rank = $args[0]>><<set $DrugSellPolice = $args[1]>><<set $DrugSellOpp = $args[2]>><<set _random = random(99)+1>><<set $DrugSellRank = _rank>><<if $TalkDealer3 == true>><<if _random <= 20>><<set $DrugSellType = "weed">><<elseif _random <= 60>><<set $DrugSellType = "coke">><<else>><<set $DrugSellType = "meth">><</if>><<elseif $TalkDealer2 == true>><<if _random <= 40>><<set $DrugSellType = "weed">><<else>><<set $DrugSellType = "coke">><</if>><<elseif $TalkDealer1 == true>><<set $DrugSellType = "weed">><</if>><<link "<em>Someone approaches you…</em>">><<SetReturnTo>><<goto "DrugSell">><</link>><</widget>>
<<widget "DealerSellRenderBottom">><<if $DealerSellEvent is "idle">><br><<BottomButton "Action">><<link "💰 Sell">><<set $Hour++>><<script>>$(document).trigger("dealer:sell");<</script>><</link>><</BottomButton>><br><<BottomButton "Move">><<ReturnTo>><</BottomButton>><<else>><br><<BottomButton "Move">><<ReturnTo>><</BottomButton>><</if>><</widget>>
<<widget "DealerSellRenderResult">><style>
.dsr-wrap{display:flex;flex-direction:column;gap:6px;font-family:inherit;}
.dsr-head{display:flex;align-items:center;gap:10px;font-size:calc(15px + var(--font-boost,0px));font-weight:900;color:rgba(255,255,255,.90);line-height:1.4;}
.dsr-head-ic{font-size:calc(20px + var(--font-boost,0px));flex-shrink:0;}
.dsr-warn .dsr-head{color:rgba(255,200,0,.90);}
.dsr-err .dsr-head{color:rgba(230,87,99,.95);}
.dsr-head strong{color:#fff;}
.dsr-fx{font-size:calc(13px + var(--font-boost,0px));font-weight:600;font-style:italic;color:rgba(230,87,99,.70);}
</style><<if $DealerSellEvent is "none">><<InformationUiPopUp "Deal">><div class="dsr-wrap"><div class="dsr-head"><span class="dsr-head-ic">ℹ️</span><span>Select at least 1 unit to sell.</span></div></div><</InformationUiPopUp>><<elseif $DealerSellEvent is "wrongType">><<InformationUiPopUp "Deal">><div class="dsr-wrap dsr-err"><div class="dsr-head"><span class="dsr-head-ic">❌</span><span>The client wanted <strong><<= $DealerSellEventData.typeWanted >></strong>! Transaction canceled.</span></div><div class="dsr-fx">-5 Reputation</div></div><</InformationUiPopUp>><<elseif $DealerSellEvent is "notExact">><<InformationUiPopUp "Deal">><div class="dsr-wrap dsr-warn"><div class="dsr-head"><span class="dsr-head-ic">⚠️</span><span>The client wanted exactly <strong><<= $DealerSellEventData.wanted >></strong> unit(s). Transaction canceled.</span></div><div class="dsr-fx">-5 Reputation</div></div><</InformationUiPopUp>><<elseif $DealerSellEvent is "ok">><<set $DealerTxn={rank:+$DealerSellEventData.rankNum,policePct:+$DealerSellEventData.policePct,rivalPct:+$DealerSellEventData.rivalPct,wanted:+$DealerSellEventData.wanted,type:String($DealerSellEventData.typeWanted||"").trim(),selected:$DealerSellEventData.chosen,totalCount:+$DealerSellEventData.totalCount,totalPayout:+$DealerSellEventData.totalPayout}>><<DealerSell $DealerSellEventData.rankNum $DealerSellEventData.policePct $DealerSellEventData.rivalPct>><</if>><</widget>>
<<widget "DealerSellListItems">><<set $DealerTemp={wanted:+$args[0],rankNum:+$args[1],policePct:+$args[2],rivalPct:+$args[3],typeWanted:String($args[4]||"").trim(),sellables:[]}>><<set $DealerSelections={}>><<set $DealerSellEvent="idle">><<set $DealerSellEventData={}>><<set _rankKey=$DealerTemp.rankNum>><<set _priceTable=$DealerSellItems[_rankKey]>><<for _i=0;_i<$IllegalItems.length;_i++>><<set _id=$IllegalItems[_i]>><<set _it=$Inventory[_id]>><<if _it&&(+_it.qty>0)>><<set $DealerTemp.sellables.push({id:_id,name:(_it.name||_id),qty:+_it.qty})>><</if>><</for>><<if $DealerTemp.sellables.length>0>><<set _tw=$DealerTemp.typeWanted>><<if !_tw||!$Inventory[_tw]||+(($Inventory[_tw]&&$Inventory[_tw].qty)||0)<=0>><<set $DealerTemp.typeWanted=$DealerTemp.sellables[Math.floor(Math.random()*$DealerTemp.sellables.length)].id>><</if>><<set $DealerTemp.sellables=$DealerTemp.sellables.filter(function(s){return s.id===$DealerTemp.typeWanted;})>><</if>><<if $DealerTemp.sellables.length==0>><<InformationUiPopUp "Deal">>You have nothing to sell...<</InformationUiPopUp>><div class="BottomUiBarCustom"><br><<BottomButton "Move">><<ReturnTo>><</BottomButton>></div><<else>><div id="dealer-container" class="dsl-wrap"><div class="dsl-note"><span class="dsl-note-ic">💡</span><span>You can sell in different zones. Each zone has its own difficulty level: the harder it is to sell, the higher the price you get for your products.</span></div><div class="dsl-request"><div class="dsl-req-ic">🤝</div><div class="dsl-req-txt">The client wants <strong><<= $DealerTemp.wanted >></strong> unit(s) of <strong><<= $DealerTemp.typeWanted >></strong></div></div><div class="dsl-items"><<for _i=0;_i<$DealerTemp.sellables.length;_i++>><<set _row=$DealerTemp.sellables[_i]>><<set _unit=(_priceTable&&_priceTable[_row.id])?_priceTable[_row.id]:0>><<print '<div class="dsl-card" data-unit="'+_unit+'"><div class="dsl-card-top"><div class="dsl-card-name">'+_row.name+'</div><div class="dsl-card-price">'+_unit+'$ <span class="dsl-per">/unit</span></div></div><div class="dsl-card-bottom"><div class="dsl-stock">In stock: <strong>'+_row.qty+'</strong></div><div class="dsl-stepper"><button type="button" class="dsl-step" data-step="-1">−</button><input class="sell-input" data-id="'+_row.id+'" type="number" min="0" max="'+_row.qty+'" step="1" value="0"><button type="button" class="dsl-step" data-step="1">+</button></div></div></div>'>><</for>></div><div class="dsl-total-bar"><span class="dsl-total-lbl">Estimated payout</span><span class="dsl-total-val" id="dsl-total">0$</span></div></div><div class="BottomUiBarCustom"><span style="display:contents;" id="dealer-actions"><<DealerSellRenderBottom>></span></div><div id="dealer-result"></div><style>
.dsl-wrap{max-width:560px;margin:0 auto;display:flex;flex-direction:column;gap:10px;font-family:inherit;padding:0 4px;}
.dsl-note{display:flex;gap:10px;align-items:flex-start;padding:12px 14px;border-radius:10px;background:rgba(230,87,99,.06);border:1px solid rgba(230,87,99,.20);font-size:calc(14px + var(--font-boost,0px));font-weight:600;color:rgba(255,255,255,.72);line-height:1.5;}
.dsl-note-ic{font-size:calc(16px + var(--font-boost,0px));flex-shrink:0;line-height:1.4;}
.dsl-request{display:flex;align-items:center;gap:12px;padding:14px 16px;border-radius:12px;background:rgba(255,255,255,.04);border:1px solid rgba(255,255,255,.10);}
.dsl-req-ic{font-size:calc(22px + var(--font-boost,0px));flex-shrink:0;}
.dsl-req-txt{font-size:calc(14px + var(--font-boost,0px));font-weight:600;color:rgba(255,255,255,.80);line-height:1.45;}
.dsl-req-txt strong{color:rgba(230,87,99,.95);font-weight:900;}
.dsl-items{display:flex;flex-direction:column;gap:8px;}
.dsl-card{border-radius:12px;background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.09);padding:12px 14px;display:flex;flex-direction:column;gap:10px;transition:border-color .12s;}
.dsl-card:hover{border-color:rgba(230,87,99,.30);}
.dsl-card-top{display:flex;align-items:center;justify-content:space-between;gap:10px;flex-wrap:wrap;}
.dsl-card-name{font-size:calc(15px + var(--font-boost,0px));font-weight:900;color:rgba(255,255,255,.90);}
.dsl-card-price{font-size:calc(15px + var(--font-boost,0px));font-weight:900;color:#3ecf8e;white-space:nowrap;}
.dsl-per{font-size:calc(12px + var(--font-boost,0px));font-weight:600;color:rgba(255,255,255,.40);}
.dsl-card-bottom{display:flex;align-items:center;justify-content:space-between;gap:10px;flex-wrap:wrap;}
.dsl-stock{font-size:calc(14px + var(--font-boost,0px));font-weight:600;color:rgba(255,255,255,.50);}
.dsl-stock strong{color:rgba(255,255,255,.85);}
.dsl-stepper{display:flex;align-items:center;gap:6px;}
.dsl-step{all:unset;width:32px;height:32px;border-radius:8px;border:1px solid rgba(255,255,255,.14);background:rgba(255,255,255,.05);color:rgba(255,255,255,.85);font-size:calc(18px + var(--font-boost,0px));font-weight:900;cursor:pointer;display:flex;align-items:center;justify-content:center;line-height:1;transition:background .10s,border-color .10s;user-select:none;}
.dsl-step:hover{background:rgba(230,87,99,.14);border-color:rgba(230,87,99,.35);color:rgba(230,87,99,.95);}
.dsl-step:active{transform:scale(.94);}
.dsl-wrap .sell-input{width:64px;height:32px;text-align:center;border-radius:8px;border:1px solid rgba(255,255,255,.14);background:rgba(0,0,0,.35);color:#fff;font-size:calc(15px + var(--font-boost,0px));font-weight:900;font-family:inherit;outline:none;-moz-appearance:textfield;}
.dsl-wrap .sell-input::-webkit-outer-spin-button,.dsl-wrap .sell-input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0;}
.dsl-wrap .sell-input:focus{border-color:rgba(230,87,99,.55);box-shadow:0 0 0 2px rgba(230,87,99,.15);}
.dsl-total-bar{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:12px 16px;border-radius:12px;background:rgba(62,207,142,.06);border:1px solid rgba(62,207,142,.22);}
.dsl-total-lbl{font-size:calc(13px + var(--font-boost,0px));font-weight:800;letter-spacing:.06em;text-transform:uppercase;color:rgba(255,255,255,.55);}
.dsl-total-val{font-size:calc(18px + var(--font-boost,0px));font-weight:950;color:#3ecf8e;}
@media(max-width:480px){
.dsl-card-top,.dsl-card-bottom{flex-direction:row;}
.dsl-request{padding:12px;}
.dsl-note{padding:10px 12px;}
}
.dmg-wrap{padding:20px 16px;border-radius:12px;background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.08);font-family:inherit;}
.dmg-scene{display:flex;flex-direction:column;align-items:center;gap:14px;padding:10px 0 20px 0;}
.dmg-buyer-wrap{display:flex;flex-direction:column;align-items:center;gap:6px;}
.dmg-countdown{font-size:clamp(32px,6vw,48px);font-weight:950;color:rgba(255,255,255,.90);line-height:1;transition:opacity 0.3s ease;min-height:56px;text-align:center;letter-spacing:-.02em;}
.dmg-silhouette{font-size:clamp(48px,8vw,72px);line-height:1;opacity:.15;filter:grayscale(1);}
.dmg-bar-wrap{width:200px;height:3px;border-radius:999px;background:rgba(255,255,255,.08);overflow:hidden;}
.dmg-bar{height:100%;border-radius:999px;background:#e65763;width:100%;box-shadow:0 0 8px rgba(230,87,99,.40);}
.dmg-hint{font-size:calc(12px + var(--font-boost,0px));font-weight:800;color:rgba(255,255,255,.55);letter-spacing:.06em;}
.dmg-btns{display:flex;gap:8px;flex-wrap:wrap;justify-content:center;}
.dmg-btn{all:unset;padding:9px 20px;border-radius:10px;font-size:calc(12px + var(--font-boost,0px));font-weight:950;letter-spacing:.06em;cursor:pointer;transition:background .10s,transform .10s;border:1px solid rgba(255,255,255,.10);background:rgba(255,255,255,.05);color:rgba(255,255,255,.82);}
.dmg-btn:hover{transform:translateY(-1px);background:rgba(255,255,255,.09);}
.dmg-sell{background:rgba(230,87,99,.10)!important;border-color:rgba(230,87,99,.28)!important;color:rgba(230,87,99,.92)!important;}
.dmg-sell:hover{background:rgba(230,87,99,.18)!important;}
.dmg-choice-bar-wrap{width:200px;height:3px;border-radius:999px;background:rgba(255,255,255,.08);overflow:hidden;margin-top:4px;}
.dmg-choice-bar{height:100%;border-radius:999px;background:rgba(255,200,0,.70);box-shadow:0 0 8px rgba(255,200,0,.30);}
</style><<script>>(function(){setTimeout(function(){var V=State.variables,D=V.DealerTemp,inputs=Array.prototype.slice.call(document.querySelectorAll('.sell-input')),actionsWrap=document.getElementById("dealer-actions"),container=document.getElementById("dealer-container"),box=document.getElementById("dealer-result");function updateTotal(){var total=0;document.querySelectorAll('.dsl-card').forEach(function(card){var unit=+card.getAttribute('data-unit')||0;var inp=card.querySelector('.sell-input');if(inp){total+=unit*(parseInt(inp.value,10)||0);}});var tEl=document.getElementById('dsl-total');if(tEl)tEl.textContent=total+'$';}inputs.forEach(function(inp){var id=String(inp.getAttribute('data-id')||'').trim(),max=+inp.getAttribute('max')||0;V.DealerSelections[id]=0;var handler=function(){var val=parseInt(inp.value,10);if(isNaN(val))val=0;val=Math.max(0,Math.min(max,val));inp.value=String(val);V.DealerSelections[id]=val;updateTotal();};inp.addEventListener('input',handler);inp.addEventListener('change',handler);});document.querySelectorAll('.dsl-step').forEach(function(btn){btn.addEventListener('click',function(){var card=btn.closest('.dsl-card');if(!card)return;var inp=card.querySelector('.sell-input');if(!inp)return;var step=+btn.getAttribute('data-step')||0;var max=+inp.getAttribute('max')||0;var val=(parseInt(inp.value,10)||0)+step;val=Math.max(0,Math.min(max,val));inp.value=String(val);inp.dispatchEvent(new Event('input'));});});updateTotal();function showDealerMiniGame(buyerType,targetBox,cb){var ICON_MS=750;var COUNTDOWN_INTERVAL=750;var CHOICE_MS=6000;var icons={cop:'🚓',rival:'🔪',regular:'💰'};var icon=icons[buyerType]||'💰';var wrap=document.createElement('div');wrap.className='dmg-wrap';wrap.innerHTML='<div class="dmg-scene"><div class="dmg-buyer-wrap"><div class="dmg-countdown" id="dmg-countdown">3</div><div class="dmg-silhouette">🚶</div></div><div class="dmg-bar-wrap"><div class="dmg-bar" id="dmg-bar" style="width:100%;transition:none;"></div></div><div class="dmg-hint" id="dmg-hint">Someone is approaching...</div></div><div class="dmg-btns" id="dmg-btns" style="display:none;"><button class="dmg-btn dmg-sell" data-choice="sell">💰 Sell</button><button class="dmg-btn dmg-ignore" data-choice="ignore">🙈 Ignore</button><button class="dmg-btn dmg-flee" data-choice="flee">🏃 Flee</button></div><div class="dmg-choice-bar-wrap" id="dmg-choice-bar-wrap" style="display:none;"><div class="dmg-choice-bar" id="dmg-choice-bar"></div></div>';targetBox.innerHTML='';targetBox.appendChild(wrap);var n=3;var countEl=document.getElementById('dmg-countdown');var hintEl=document.getElementById('dmg-hint');var bar=document.getElementById('dmg-bar');var btnsEl=document.getElementById('dmg-btns');var choiceBarWrap=document.getElementById('dmg-choice-bar-wrap');var choiceBar=document.getElementById('dmg-choice-bar');var handled=false;var choiceTimer=null;var interval=setInterval(function(){n--;if(countEl)countEl.textContent=String(n>0?n:'');if(n<=0){clearInterval(interval);if(countEl)countEl.textContent=icon;if(hintEl)hintEl.textContent='Who is it?';if(bar){bar.style.transition='width '+ICON_MS+'ms linear';requestAnimationFrame(function(){bar.style.width='0%';});}setTimeout(function(){if(countEl)countEl.style.opacity='0';if(hintEl)hintEl.textContent='Decide now!';if(btnsEl)btnsEl.style.display='flex';if(choiceBarWrap)choiceBarWrap.style.display='block';if(choiceBar){choiceBar.style.transition='none';choiceBar.style.width='100%';requestAnimationFrame(function(){choiceBar.style.transition='width '+CHOICE_MS+'ms linear';requestAnimationFrame(function(){choiceBar.style.width='0%';});});}choiceTimer=setTimeout(function(){if(handled)return;handled=true;wrap.remove();cb('flee');},CHOICE_MS);document.querySelectorAll('.dmg-btn').forEach(function(btn){btn.addEventListener('click',function(){if(handled)return;handled=true;if(choiceTimer)clearTimeout(choiceTimer);wrap.remove();cb(btn.getAttribute('data-choice'));});});},ICON_MS);}},COUNTDOWN_INTERVAL);}$(document).off("dealer:sell.dealer").on("dealer:sell.dealer",function(){if(!D)return;V.DealerSellEvent="";V.DealerSellEventData={};var wanted=+D.wanted,rankNum=+D.rankNum,policePct=+D.policePct,rivalPct=+D.rivalPct,typeWanted=String(D.typeWanted||"").trim();var priceTable=(V.DealerSellItems&&V.DealerSellItems[rankNum])||{};var chosen=[],totalCount=0,totalPayout=0,wrongType=false;Object.keys(V.DealerSelections).forEach(function(id){var q=+V.DealerSelections[id]||0;if(q>0){var max=0;(D.sellables||[]).forEach(function(s){if(s.id===id){max=+s.qty||0;}});q=Math.max(0,Math.min(max,q));var unit=priceTable[id]||0;chosen.push({id:id,name:(V.Inventory[id]&&V.Inventory[id].name)||id,qty:q,unit:unit});totalCount+=q;totalPayout+=q*unit;if(String(id).trim().toLowerCase()!==String(typeWanted).trim().toLowerCase()){wrongType=true;}}});if(totalCount>wanted){var remaining=wanted,capped=[],newCount=0,newPayout=0;chosen.forEach(function(c){if(remaining<=0)return;var take=Math.min(+c.qty||0,remaining);if(take>0){capped.push({id:c.id,name:c.name,qty:take,unit:c.unit});newCount+=take;newPayout+=take*(+c.unit||0);remaining-=take;}});chosen=capped;totalCount=newCount;totalPayout=newPayout;}if(!box)return;box.innerHTML="";if(totalCount===0){if(actionsWrap){actionsWrap.innerHTML="";actionsWrap.appendChild(Wikifier.wikifyEval('<<set $DealerSellEvent="after">><<DealerSellRenderBottom>>'));}if(container)container.remove();V.DealerSellEvent="none";V.DealerSellEventData={};box.appendChild(Wikifier.wikifyEval('<<DealerSellRenderResult>>'));return;}if(wrongType){if(actionsWrap){actionsWrap.innerHTML="";actionsWrap.appendChild(Wikifier.wikifyEval('<<set $DealerSellEvent="after">><<DealerSellRenderBottom>>'));}if(container)container.remove();V.Reputation=(V.Reputation||0)-5;V.DealerSellEvent="wrongType";V.DealerSellEventData={typeWanted:typeWanted,wanted:wanted,rankNum:rankNum,policePct:policePct,rivalPct:rivalPct};box.appendChild(Wikifier.wikifyEval('<<DealerSellRenderResult>>'));return;}if(totalCount<wanted){if(actionsWrap){actionsWrap.innerHTML="";actionsWrap.appendChild(Wikifier.wikifyEval('<<set $DealerSellEvent="after">><<DealerSellRenderBottom>>'));}if(container)container.remove();V.Reputation=(V.Reputation||0)-5;V.DealerSellEvent="notExact";V.DealerSellEventData={typeWanted:typeWanted,wanted:wanted,rankNum:rankNum,policePct:policePct,rivalPct:rivalPct};box.appendChild(Wikifier.wikifyEval('<<DealerSellRenderResult>>'));return;}if(actionsWrap)actionsWrap.innerHTML="";if(container)container.remove();var rollPolice=Math.floor(Math.random()*100)+1;var caughtByPolice=(rollPolice<=policePct);var rollRival=caughtByPolice?null:(Math.floor(Math.random()*100)+1);var caughtByRival=!caughtByPolice&&(rollRival<=rivalPct);var buyerType=caughtByPolice?'cop':(caughtByRival?'rival':'regular');var eventData={typeWanted:typeWanted,wanted:wanted,rankNum:rankNum,policePct:policePct,rivalPct:rivalPct,chosen:chosen,totalCount:totalCount,totalPayout:totalPayout};if(V.OptSkipMiniGamesOn===true){V.DealerPreRoll={cop:caughtByPolice,rival:caughtByRival,rollPolice:rollPolice,rollRival:rollRival||0};V.DealerSellEvent="ok";V.DealerSellEventData=eventData;if(actionsWrap)actionsWrap.innerHTML="";if(container)container.remove();box.appendChild(Wikifier.wikifyEval('<<DealerSellRenderResult>>'));return;}showDealerMiniGame(buyerType,box,function(choice){box.innerHTML='';if(choice==='ignore'){var ignoreRoll=Math.random()<0.5;if(buyerType==='regular'||ignoreRoll){box.appendChild(Wikifier.wikifyEval('<<InformationUiPopUp "Deal">>🙈 You let them pass. No sale made.<</InformationUiPopUp>>'));if(actionsWrap)actionsWrap.appendChild(Wikifier.wikifyEval('<<set $DealerSellEvent="after">><<DealerSellRenderBottom>>'));}else if(buyerType==='cop'){V.DealerPreRoll={cop:true,rival:false,rollPolice:100,rollRival:null};V.DealerSellEvent="ok";V.DealerSellEventData=eventData;box.appendChild(Wikifier.wikifyEval('<<DealerSellRenderResult>>'));}else{V.DealerPreRoll={cop:false,rival:true,rollPolice:0,rollRival:100};V.DealerSellEvent="ok";V.DealerSellEventData=eventData;box.appendChild(Wikifier.wikifyEval('<<DealerSellRenderResult>>'));}}else if(choice==='flee'){V.Stress=(V.Stress||0)+15;box.appendChild(Wikifier.wikifyEval('<<InformationUiPopUp "Deal">>🏃 You quickly walk away. <em>(+15 Stress)</em><</InformationUiPopUp>>'));if(actionsWrap)actionsWrap.appendChild(Wikifier.wikifyEval('<<set $DealerSellEvent="after">><<DealerSellRenderBottom>>'));}else{V.DealerPreRoll={cop:caughtByPolice,rival:caughtByRival,rollPolice:rollPolice,rollRival:rollRival||0};V.DealerSellEvent="ok";V.DealerSellEventData=eventData;box.appendChild(Wikifier.wikifyEval('<<DealerSellRenderResult>>'));}});});},100);})();<</script>><</if>><</widget>>
<<widget "DealerSell">><<set _tx=$DealerTxn>><<set _hasSlot = $("#dealer-actions").length>><<if !_tx or !_tx.selected or _tx.selected.length==0>><<InformationUiPopUp "Deal">>No items selected for sale.<</InformationUiPopUp>><<if _hasSlot>><<replace "#dealer-actions">><br><<BottomButton "Move">><<ReturnTo>><</BottomButton>><</replace>><<else>><div class="BottomUiBarCustom"><br><<BottomButton "Move">><<ReturnTo>><</BottomButton>></div><</if>><<else>><<set _policePct=Math.max(0,Math.min(100,+$DealerTxn.policePct||0))>><<set _rivalPct=Math.max(0,Math.min(100,+$DealerTxn.rivalPct||0))>><<if $DealerPreRoll>><<set _caughtByPolice=$DealerPreRoll.cop>><<set _rollPolice=$DealerPreRoll.rollPolice>><<set _caughtByRival=$DealerPreRoll.rival>><<set _rollRival=$DealerPreRoll.rollRival||null>><<set $DealerPreRoll=null>><<else>><<set _rollPolice=Math.floor(Math.random()*100)+1>><<set _caughtByPolice=(_rollPolice<=_policePct)>><<if !_caughtByPolice>><<set _rollRival=Math.floor(Math.random()*100)+1>><<set _caughtByRival=(_rollRival<=_rivalPct)>><<else>><<set _rollRival=null>><<set _caughtByRival=false>><</if>><</if>><<if _caughtByPolice>><div id="dealer-police-block"><<InformationUiPopUp "Deal">><<script>>(function(){try{var V=State.variables;if(!V._PoliceSfxLoopOn){V._PoliceSfxLoopOn=true;if(window.setup&&setup.AudioMixer&&typeof setup.AudioMixer.playPlaylist==="function"){setup.AudioMixer.playPlaylist("sfx","sfx.police",true,{fadeInMs:0,fadeOutMs:0});}else if(window.SugarCube&&SugarCube.Sound&&typeof SugarCube.Sound.play==="function"){try{SugarCube.Sound.play("sfx.police",{loop:true});}catch(e){SugarCube.Sound.play("sfx.police");}}}}catch(e){}})();<</script>>🚓 The police intercept you !<</InformationUiPopUp>><<if _hasSlot>><<replace "#dealer-actions">><br><<BottomButton "Action">><<link "Flee from the police">><<set _fleePct=Math.max(0,Math.min(100,+$Fitness||0))>><<set _fleeRoll=Math.floor(Math.random()*100)+1>><<set _fleeOK=(_fleeRoll<=_fleePct)>><<if _fleeOK>><<replace "#dealer-police-block">><<InformationUiPopUp "Deal">>🏃♂️ You manage to lose the police!<br>(Roll: <strong><<= _fleeRoll >></strong> / Chance: <strong><<= _fleePct >>%</strong>)<br><em>You barely escape and get back to your business…</em><br><em>(+30 Stress)</em><</InformationUiPopUp>><<set $Stress += 30>><</replace>><<replace "#dealer-actions">><br><<BottomButton "Move">><<script>>(function(){try{var V=State.variables;V._PoliceSfxLoopOn=false;if(window.setup&&setup.AudioMixer&&typeof setup.AudioMixer.stopPlaylist==="function"){setup.AudioMixer.stopPlaylist("sfx");}else if(window.setup&&setup.AudioMixer&&typeof setup.AudioMixer.stop==="function"){setup.AudioMixer.stop("sfx");}else if(window.SugarCube&&SugarCube.Sound&&typeof SugarCube.Sound.stop==="function"){SugarCube.Sound.stop("sfx.police");}}catch(e){}})();<</script>><<ReturnTo>><</BottomButton>><</replace>><<else>><<replace "#dealer-police-block">><<PoliceInter>><</replace>><</if>><</link>><br><<link "Surrender to the police">><<replace "#dealer-police-block">><<PoliceInter>><</replace>><</link>><</BottomButton>><</replace>><<else>><div class="BottomUiBarCustom"><br><<BottomButton "Action">><<link "Flee from the police">><<set _fleePct=Math.max(0,Math.min(100,+$Fitness||0))>><<set _fleeRoll=Math.floor(Math.random()*100)+1>><<set _fleeOK=(_fleeRoll<=_fleePct)>><<if _fleeOK>><<replace "#dealer-police-block">><<InformationUiPopUp "Deal">>🏃♂️ You manage to lose the police!<br>(Roll: <strong><<= _fleeRoll >></strong> / Chance: <strong><<= _fleePct >>%</strong>)<br><em>You barely escape and get back to your business…</em><br><em>(+30 Stress)</em><</InformationUiPopUp>><<set $Stress += 30>><div class="BottomUiBarCustom"><br><<BottomButton "Move">><<script>>(function(){try{var V=State.variables;V._PoliceSfxLoopOn=false;if(window.setup&&setup.AudioMixer&&typeof setup.AudioMixer.stopPlaylist==="function"){setup.AudioMixer.stopPlaylist("sfx");}else if(window.setup&&setup.AudioMixer&&typeof setup.AudioMixer.stop==="function"){setup.AudioMixer.stop("sfx");}else if(window.SugarCube&&SugarCube.Sound&&typeof SugarCube.Sound.stop==="function"){SugarCube.Sound.stop("sfx.police");}}catch(e){}})();<</script>><<ReturnTo>><</BottomButton>></div><</replace>><<else>><<replace "#dealer-police-block">><<PoliceInter>><</replace>><</if>><</link>><</BottomButton>><br><<BottomButton "Action">><<link "Surrender to the police">><<replace "#dealer-police-block">><<PoliceInter>><</replace>><</link>><</BottomButton>></div><</if>></div><<elseif _caughtByRival>><div id="dealer-rival-block"><<InformationUiPopUp "Deal">>🔪 A rival gang shows up !<</InformationUiPopUp>><<if _hasSlot>><<replace "#dealer-actions">><br><<BottomButton "Action">><<link "Flee the gang">><<set _fleePct=Math.max(0,Math.min(100,+$Fitness||0))>><<set _fleeRoll=Math.floor(Math.random()*100)+1>><<set _fleeOK=(_fleeRoll<=_fleePct)>><<if _fleeOK>><<replace "#dealer-rival-block">><<InformationUiPopUp "Deal">>🏃♂️ You manage to escape the rival gang!<br>(Roll: <strong><<= _fleeRoll >></strong> / Chance: <strong><<= _fleePct >>%</strong>)<br><em>You quickly move away from the area…</em><br><em>(+30 Stress)</em><</InformationUiPopUp>><<set $Stress += 30>><</replace>><<replace "#dealer-actions">><br><<BottomButton "Move">><<ReturnTo>><</BottomButton>><</replace>><<else>><<set _random=random(25,75)>><<set $Fight={type:"Dealer",lvl:random(10,75),playerMax:+$Heal||100,enemyMax:100,playerHP:+$Heal||100,enemyHP:100,playerBand:0,enemyBand:(function(){var r=random(1,10);return r<=5?0:r<=8?1:2;})(),playerStaMax:5,playerSta:5,healCD:0,log:[],p:{stun:0,bleed:0,bleedDmg:0,guard:0,exposed:0,adr:0},e:{stun:0,bleed:0,bleedDmg:0,guard:0,exposed:0,adr:0},enemyAtkMul:1,enemyDodgeBias:0.40}>><<set $ReturnTo = "DrugSell">><<script>>Engine.play("Fight");<</script>><</if>><</link>><br><<link "Fight">><<set $ReturnTo = "DrugSell">><<set $Fight={type:"Dealer",lvl:random(10,75),playerMax:+$Heal||100,enemyMax:100,playerHP:+$Heal||100,enemyHP:100,playerBand:0,enemyBand:(function(){var r=random(1,10);return r<=5?0:r<=8?1:2;})(),playerStaMax:5,playerSta:5,healCD:0,log:[],p:{stun:0,bleed:0,bleedDmg:0,guard:0,exposed:0,adr:0},e:{stun:0,bleed:0,bleedDmg:0,guard:0,exposed:0,adr:0},enemyAtkMul:1,enemyDodgeBias:0.40}>><<script>>Engine.play("Fight");<</script>><</link>><</BottomButton>><</replace>><<else>><div class="BottomUiBarCustom"><br><<BottomButton "Action">><<link "Flee the gang">><<set _fleePct=Math.max(0,Math.min(100,+$Fitness||0))>><<set _fleeRoll=Math.floor(Math.random()*100)+1>><<set _fleeOK=(_fleeRoll<=_fleePct)>><<if _fleeOK>><<replace "#dealer-rival-block">><<InformationUiPopUp "Deal">>🏃♂️ You manage to escape the rival gang!<br>(Roll: <strong><<= _fleeRoll >></strong> / Chance: <strong><<= _fleePct >>%</strong>)<br><em>You quickly move away from the area…</em><br><em>(+30 Stress)</em><</InformationUiPopUp>><<set $Stress += 30>><div class="BottomUiBarCustom"><br><<BottomButton "Move">><<ReturnTo>><</BottomButton>></div><</replace>><<else>><<set _random=random(25,75)>><<Fight "Dealer" _random>><</if>><</link>><</BottomButton>><br><<BottomButton "Action">><<link "Fight">><<set _random=random(25,75)>><<Fight "Dealer" _random>><</link>><</BottomButton>></div><</if>></div><<else>><<for _i=0;_i<_tx.selected.length;_i++>><<set _s=_tx.selected[_i]>><<if $Inventory[_s.id]>><<set $Inventory[_s.id].qty=Math.max(0,(+$Inventory[_s.id].qty||0)-(+_s.qty||0))>><</if>><</for>><<set $Money+= (+_tx.totalPayout||0)>><<InformationUiPopUp "Deal">>✅ Sale successful!<br><ul><<for _i=0;_i<_tx.selected.length;_i++>><<set _s=_tx.selected[_i]>><li><strong><<= _s.name >></strong> sold: <<= _s.qty >> × <<= _s.unit >>$</li><</for>></ul><br>Total received: <strong><<= _tx.totalPayout >></strong>$<br><em>(+1 Reputation)</em><</InformationUiPopUp>><<set $Ach_Count_Deal_Weed += _s.qty>><<set $Reputation += 1>><<if _hasSlot>><<replace "#dealer-actions">><br><<BottomButton "Move">><<ReturnTo>><</BottomButton>><</replace>><<else>><div class="BottomUiBarCustom"><br><<BottomButton "Move">><<ReturnTo>><</BottomButton>></div><</if>><</if>><</if>><</widget>>
<<widget "PoliceInter">><<set _hasSlot=$("#dealer-actions").length>><<script>>(function(){try{var V=State.variables;if(!V._PoliceSfxLoopOn){V._PoliceSfxLoopOn=true;if(window.setup&&setup.AudioMixer&&typeof setup.AudioMixer.playPlaylist==="function"){setup.AudioMixer.playPlaylist("sfx","sfx.police",true,{fadeInMs:0,fadeOutMs:0});}else if(window.SugarCube&&SugarCube.Sound&&typeof SugarCube.Sound.play==="function"){try{SugarCube.Sound.play("sfx.police",{loop:true});}catch(e){SugarCube.Sound.play("sfx.police");}}}}catch(e){}})();<</script>><<script>>(function(){var V=State.variables,inv=V.Inventory||{},illegal=Array.isArray(V.IllegalItems)?V.IllegalItems.map(function(i){return String(i).toLowerCase();}):[],FINES={coke:75,meth:110},PER_DEFAULT=50,seized=[],totalQty=0,fine=0;for(var key in inv){if(!Object.prototype.hasOwnProperty.call(inv,key))continue;var item=inv[key],id=String((item&&item.id)?item.id:key).toLowerCase();if(illegal.indexOf(id)===-1)continue;var qty=(item&&Number.isFinite(+item.qty))?+item.qty:0;if(qty<=0){delete inv[key];continue;}var per=Object.prototype.hasOwnProperty.call(FINES,id)?FINES[id]:PER_DEFAULT;var name=(item&&item.name)?String(item.name):(item&&item.id)?String(item.id):key,sum=per*qty;seized.push({id:id,name:name,qty:qty,perFine:per,sum:sum});totalQty+=qty;fine+=sum;delete inv[key];}V.PoliceSeized=seized;V.PoliceSeizedCount=totalQty;V.PoliceFine=fine;if(Number.isFinite(+V.Bank)){V.Bank=(+V.Bank)-fine;}else{V.Money=(+V.Money||0)-fine;}})();<</script>><style>
.pol-wrap{display:flex;flex-direction:column;gap:8px;font-family:inherit;}
.pol-head{display:flex;align-items:center;gap:10px;font-size:calc(15px + var(--font-boost,0px));font-weight:900;color:rgba(255,255,255,.90);}
.pol-head-ic{font-size:calc(20px + var(--font-boost,0px));}
.pol-list{display:flex;flex-direction:column;gap:6px;margin:4px 0;}
.pol-item{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:9px 12px;border-radius:9px;background:rgba(230,87,99,.05);border:1px solid rgba(230,87,99,.16);flex-wrap:wrap;}
.pol-item-name{font-size:calc(14px + var(--font-boost,0px));font-weight:800;color:rgba(255,255,255,.85);}
.pol-item-detail{font-size:calc(13px + var(--font-boost,0px));font-weight:600;color:rgba(255,255,255,.50);}
.pol-item-sum{font-size:calc(14px + var(--font-boost,0px));font-weight:900;color:rgba(230,87,99,.92);white-space:nowrap;}
.pol-total{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:11px 12px;border-radius:9px;background:rgba(230,87,99,.10);border:1px solid rgba(230,87,99,.30);flex-wrap:wrap;}
.pol-total-lbl{font-size:calc(13px + var(--font-boost,0px));font-weight:800;letter-spacing:.05em;text-transform:uppercase;color:rgba(255,255,255,.60);}
.pol-total-val{font-size:calc(16px + var(--font-boost,0px));font-weight:950;color:rgba(230,87,99,1);}
.pol-stress{font-size:calc(13px + var(--font-boost,0px));font-weight:600;font-style:italic;color:rgba(255,255,255,.42);}
</style><div id="police-inter-block"><<if $PoliceSeized and $PoliceSeized.length>0>><<InformationUiPopUp "Police">><div class="pol-wrap"><div class="pol-head"><span class="pol-head-ic">🚓</span><span>The police confiscate your illegal items and fine you.</span></div><div class="pol-list"><<for _i=0;_i<$PoliceSeized.length;_i++>><<set _it=$PoliceSeized[_i]>><div class="pol-item"><div><div class="pol-item-name"><<=_it.name>></div><div class="pol-item-detail"><<= _it.qty >> unit(s) × <<= _it.perFine >>$ fine</div></div><div class="pol-item-sum">-<<= _it.sum >>$</div></div><</for>></div><div class="pol-total"><span class="pol-total-lbl">Total fine · <<= $PoliceSeizedCount >> item(s) seized</span><span class="pol-total-val">-<<= $PoliceFine >>$</span></div><div class="pol-stress">(+50 Stress)</div></div><</InformationUiPopUp>><<else>><<InformationUiPopUp "Police">><div class="pol-wrap"><div class="pol-head"><span class="pol-head-ic">🚓</span><span>The police search you, but you have no illegal items on you. No fine is applied.</span></div><div class="pol-stress">(+50 Stress)</div></div><</InformationUiPopUp>><</if>></div><<if _hasSlot>><<replace "#dealer-actions">><br><<BottomButton "Move">><<link "Leave">><<set $Time++>><<set $Stress += 50>><<script>>(function(){try{var V=State.variables;V._PoliceSfxLoopOn=false;if(window.setup&&setup.AudioMixer&&typeof setup.AudioMixer.stopPlaylist==="function"){setup.AudioMixer.stopPlaylist("sfx");}else if(window.setup&&setup.AudioMixer&&typeof setup.AudioMixer.stop==="function"){setup.AudioMixer.stop("sfx");}else if(window.SugarCube&&SugarCube.Sound&&typeof SugarCube.Sound.stop==="function"){SugarCube.Sound.stop("sfx.police");}}catch(e){}})();<</script>><<goto "PoliceCell">><</link>><</BottomButton>><</replace>><<else>><div class="BottomUiBarCustom"><br><<BottomButton "Move">><<link "Leave">><<set $Time++>><<set $Stress += 50>><<script>>(function(){try{var V=State.variables;V._PoliceSfxLoopOn=false;if(window.setup&&setup.AudioMixer&&typeof setup.AudioMixer.stopPlaylist==="function"){setup.AudioMixer.stopPlaylist("sfx");}else if(window.setup&&setup.AudioMixer&&typeof setup.AudioMixer.stop==="function"){setup.AudioMixer.stop("sfx");}else if(window.SugarCube&&SugarCube.Sound&&typeof SugarCube.Sound.stop==="function"){SugarCube.Sound.stop("sfx.police");}}catch(e){}})();<</script>><<goto "PoliceCell">><</link>><</BottomButton>></div><</if>><</widget>>
<<script>>
setup.foeTypes = {
Dealer: { enemyMax: 100, bandMin: 0, bandMax: 2, atkMul: 0.95, dodgeBias: 0.60 },
};
<</script>>
<<widget "Fight">><<set _type=String($args[0]||"").trim()>><<set _lvl=Math.max(1,+$args[1]||1)>><<set _cfg=(setup.foeTypes&&setup.foeTypes[_type])?setup.foeTypes[_type]:{}>><<if _type is "Dealer">><<set _dealerFit=random(10,75)>><<set _dealerBandRoll=random(1,10)>><<set _dealerBand=(_dealerBandRoll<=5)?0:(_dealerBandRoll<=8)?1:2>><<set $Fight={type:_type,lvl:_dealerFit,playerMax:+$Heal||100,enemyMax:100,playerHP:+$Heal||100,enemyHP:100,playerBand:0,enemyBand:_dealerBand,playerStaMax:5,playerSta:5,healCD:0,log:[],p:{stun:0,bleed:0,bleedDmg:0,guard:0,exposed:0,adr:0},e:{stun:0,bleed:0,bleedDmg:0,guard:0,exposed:0,adr:0},enemyAtkMul:1,enemyDodgeBias:0.40}>><<else>><<set $Fight={type:_type,lvl:_lvl,playerMax:+$Heal||100,enemyMax:Math.max(20,+(_cfg.enemyMax||100)),playerHP:+$Heal||100,enemyHP:Math.max(20,+(_cfg.enemyMax||100)),playerBand:0,enemyBand:Math.floor(Math.random()*((+_cfg.bandMax||3)-(+_cfg.bandMin||1)+1))+(+_cfg.bandMin||1),playerStaMax:5,playerSta:5,healCD:0,log:[],p:{stun:0,bleed:0,bleedDmg:0,guard:0,exposed:0,adr:0},e:{stun:0,bleed:0,bleedDmg:0,guard:0,exposed:0,adr:0},enemyAtkMul:(+_cfg.atkMul||1),enemyDodgeBias:(+_cfg.dodgeBias||0.5)}>><<script>>(function(){SugarCube.Engine.play('Fight');})();<</script>><</if>><</widget>>
<<widget "FightStage">><<set _hasSlot=$("#dealer-actions").length>><style>
.fst-wrap{display:flex;flex-direction:column;gap:8px;font-family:inherit;}
.fst-head{display:flex;align-items:center;gap:10px;font-size:calc(15px + var(--font-boost,0px));font-weight:900;color:rgba(255,255,255,.90);}
.fst-head-ic{font-size:calc(20px + var(--font-boost,0px));}
.fst-defeat .fst-head{color:rgba(230,87,99,.95);}
.fst-victory .fst-head{color:#3ecf8e;}
.fst-effects{display:flex;flex-direction:column;gap:4px;margin-top:2px;}
.fst-fx{display:flex;align-items:center;gap:8px;font-size:calc(13px + var(--font-boost,0px));font-weight:600;color:rgba(255,255,255,.50);font-style:italic;}
.fst-fx.neg{color:rgba(230,87,99,.70);}
.fst-fx.pos{color:rgba(62,207,142,.70);}
</style><div id="fight-stage-block"><<if $Fight.playerHP<=0>><<InformationUiPopUp "Fight">><div class="fst-wrap fst-defeat"><div class="fst-head"><span class="fst-head-ic">💥</span><span>You are knocked out.</span></div><div class="fst-effects"><div class="fst-fx neg">🏥 You are transferred to the hospital (200$ fee)</div><div class="fst-fx neg">-5 Reputation</div><div class="fst-fx neg">+50 Stress</div></div></div><</InformationUiPopUp>><<elseif $Fight.enemyHP<=0>><<InformationUiPopUp "Fight">><div class="fst-wrap fst-victory"><div class="fst-head"><span class="fst-head-ic">🏆</span><span>Victory! The opponent is defeated.</span></div><div class="fst-effects"><div class="fst-fx pos">+1 Reputation</div><div class="fst-fx neg">+30 Stress</div></div></div><</InformationUiPopUp>><<set $Stress += 30>><<set $Reputation += 1>><<else>><<if $Fight.log&&$Fight.log.length>><<InformationUiPopUp "Fight">><<for _i=0;_i<$Fight.log.length;_i++>><div><<= $Fight.log[_i] >></div><</for>><</InformationUiPopUp>><</if>><</if>></div><<if $Fight.playerHP<=0>><<if _hasSlot>><<replace "#dealer-actions">><br><<BottomButton "Move">><<link "Leave">><<set $Time++>><<set $Stress += 50>><<set $Reputation -= 5>><<goto "HospitalRoom">><</link>><</BottomButton>><</replace>><<else>><div class="BottomUiBarCustom"><br><<BottomButton "Move">><<link "Leave">><<set $Time++>><<set $Stress += 50>><<set $Reputation -= 5>><<goto "HospitalRoom">><</link>><</BottomButton>></div><</if>><<elseif $Fight.enemyHP<=0>><<if _hasSlot>><<replace "#dealer-actions">><br><<BottomButton "Move">><<ReturnTo>><</BottomButton>><</replace>><<else>><div class="BottomUiBarCustom"><br><<BottomButton "Move">><<ReturnTo>><</BottomButton>></div><</if>><<else>><<if _hasSlot>><<replace "#dealer-actions">><br><<BottomButton "Move">><<ReturnTo>><</BottomButton>><</replace>><<else>><div class="BottomUiBarCustom"><br><<BottomButton "Move">><<ReturnTo>><</BottomButton>></div><</if>><</if>><</widget>>
--------------------------------------------------------------------------
<<widget "InteractMenu">><<set _npc = $args[0]>><<if !_npc or !_npc.id>><div class="iMenu-error">No NPC.</div><<else>><<set $ActiveNPC = _npc>><<set _id = String(_npc.id)>><<set $PassTalk = "Talk." + _id>><<set _lvl = +_npc.lvl || 0>><<if _npc.lvl >= 2 and $InteractInInterior == false and $Corruption.city < _npc.lvl>><<if $Corruption.city <= 1 and _npc.lvl >= 2>><<set _lvl = 1>><<else>><<set _lvl = $Corruption.city>><</if>><</if>><<set _db = setup.npcAssets[_id]>><<if !_db>><div class="iMenu-error">No assets for <<= _id >>.</div><<else>><<set _gif = "">><<set _txt = "">><<for _L to _lvl; _L >= 0; _L-->><<if _gif is "">><<set _bucket = _db["lvl"+_L]>><<if _bucket and _bucket.gifs and _bucket.gifs.length > 0>><<set _gif = _bucket.gifs.random()>><</if>><</if>><<if _txt is "">><<set _bucket = _db["lvl"+_L]>><<if _bucket and _bucket.texts and _bucket.texts.length > 0>><<set _txt = _bucket.texts.random()>><</if>><</if>><</for>><<if _gif isnot "">><<= '<img src="'+ _gif +'" alt="gif" style="max-width:100% !important;height:auto !important;object-fit:contain !important;border-radius:12px !important;display:block !important;margin:0 auto .75rem auto !important;">'>><<passagebg>><<= '<img src="'+ _gif +'" alt="gif" style="max-width:100% !important;height:auto !important;object-fit:contain !important;border-radius:8px !important;display:block !important;margin:0 auto .5rem auto !important;">'>>
<</passagebg>><</if>><<if _npc.lvl >= 2 and $InteractInInterior == false>><<if $Corruption.city < _npc.lvl>><<InformationUiPopUp "The city's Corruption level is currently too low" #e65763>><em style="display:block;margin-top:.35rem;font-size:.9rem;font-style:italic;color:rgba(200,200,200,.75);line-height:1.4;">Preventing her from dressing in a way that matches her personal level.</em><</InformationUiPopUp>><</if>><</if>><<if _txt isnot "">>
<<TalkNPC _npc _txt>><</if>><<set _talkLocked = !setup.canTalkNPC(_npc)>><<set _talkRule = setup.getTalkCondition(_npc)>><<set _noPP = _npc.lvl >= 6 ? false : $PsychicPower < 1>><<set _noSleep = _npc.lvl >= 6 ? false : _npc.lastCorruptBool === true>><<if _npc.lvl >= 6>><<set _talkLocked = false>><</if>><<set _talkLockedReason = (_npc.lvl !== _npc.talklvl) ? "level" : (_talkRule && _talkRule.condition && !setup.boolV(_talkRule.condition)) ? "condition" : "time">><div id="iMenu-pp-locked-overlay" style="display:none;position:fixed;inset:0;z-index:9999;background:rgba(0,0,0,.88);align-items:center;justify-content:center;padding:16px;box-sizing:border-box;"><div style="background:rgb(8,8,8);border:1px solid rgba(230,87,99,.30);border-radius:18px;padding:clamp(20px,3vw,32px) clamp(20px,3vw,36px);max-width:420px;width:100%;display:flex;flex-direction:column;align-items:center;gap:14px;box-shadow:0 0 40px rgba(230,87,99,.10);box-sizing:border-box;"><div style="font-size:calc(14px + var(--font-boost,0px));font-weight:900;letter-spacing:.18em;text-transform:uppercase;color:rgba(230,87,99,.70);">No Psychic Power</div><div style="font-size:calc(28px + var(--font-boost,0px));">🧠</div><div style="font-size:calc(16px + var(--font-boost,0px));font-weight:900;color:rgba(255,255,255,.92);text-align:center;line-height:1.6;letter-spacing:.01em;">You don't have enough <span style="color:rgb(230,87,99);">Psychic Power</span> to influence <<= _npc.name || "this character" >> right now.</div><div style="font-size:calc(14px + var(--font-boost,0px));font-weight:700;color:rgba(230,87,99,.75);text-align:center;line-height:1.65;"><span style="color:rgba(230,87,99,.95);font-weight:900;">Sleep</span> to restore your Psychic Power.</div><div onclick="document.getElementById('iMenu-pp-locked-overlay').style.display='none';" style="margin-top:4px;padding:12px 36px;border-radius:10px;border:1px solid rgba(230,87,99,.40);background:rgba(230,87,99,.12);color:rgb(230,87,99);font-weight:950;font-size:calc(14px + var(--font-boost,0px));letter-spacing:.14em;text-transform:uppercase;cursor:pointer;">UNDERSTOOD</div></div></div><div id="iMenu-sleep-locked-overlay" style="display:none;position:fixed;inset:0;z-index:9999;background:rgba(0,0,0,.88);align-items:center;justify-content:center;padding:16px;box-sizing:border-box;"><div style="background:rgb(8,8,8);border:1px solid rgba(230,87,99,.30);border-radius:18px;padding:clamp(20px,3vw,32px) clamp(20px,3vw,36px);max-width:420px;width:100%;display:flex;flex-direction:column;align-items:center;gap:14px;box-shadow:0 0 40px rgba(230,87,99,.10);box-sizing:border-box;"><div style="font-size:calc(14px + var(--font-boost,0px));font-weight:900;letter-spacing:.18em;text-transform:uppercase;color:rgba(230,87,99,.70);">Corruption Cooldown</div><div style="font-size:calc(28px + var(--font-boost,0px));">🌙</div><div style="font-size:calc(16px + var(--font-boost,0px));font-weight:900;color:rgba(255,255,255,.92);text-align:center;line-height:1.6;letter-spacing:.01em;">You've already influenced <span style="color:rgb(230,87,99);"><<= _npc.name || "this character" >></span> today. Her mind needs rest before going further.</div><div style="font-size:calc(14px + var(--font-boost,0px));font-weight:700;color:rgba(230,87,99,.75);text-align:center;line-height:1.65;"><span style="color:rgba(230,87,99,.95);font-weight:900;">Sleep</span> to recover and corrupt again tomorrow.</div><div onclick="document.getElementById('iMenu-sleep-locked-overlay').style.display='none';" style="margin-top:4px;padding:12px 36px;border-radius:10px;border:1px solid rgba(230,87,99,.40);background:rgba(230,87,99,.12);color:rgb(230,87,99);font-weight:950;font-size:calc(14px + var(--font-boost,0px));letter-spacing:.14em;text-transform:uppercase;cursor:pointer;">UNDERSTOOD</div></div></div><div id="iMenu-talk-locked-overlay" style="display:none;position:fixed;inset:0;z-index:9999;background:rgba(0,0,0,.88);align-items:center;justify-content:center;padding:16px;box-sizing:border-box;"><div style="background:rgb(8,8,8);border:1px solid rgba(230,87,99,.30);border-radius:18px;padding:clamp(20px,3vw,32px) clamp(20px,3vw,36px);max-width:420px;width:100%;display:flex;flex-direction:column;align-items:center;gap:14px;box-shadow:0 0 40px rgba(230,87,99,.10);box-sizing:border-box;"><div style="font-size:calc(14px + var(--font-boost,0px));font-weight:900;letter-spacing:.18em;text-transform:uppercase;color:rgba(230,87,99,.70);">Conversation Locked</div><<if _talkLockedReason === "level">><div style="font-size:calc(28px + var(--font-boost,0px));">📖</div><div style="font-size:calc(16px + var(--font-boost,0px));font-weight:900;color:rgba(255,255,255,.92);text-align:center;line-height:1.6;letter-spacing:.01em;"><<= _npc.name || "This character" >>'s story isn't ready to continue yet.<br><span style="color:rgb(230,87,99);">More needs to happen first</span> before the next conversation unlocks.</div><div style="font-size:calc(14px + var(--font-boost,0px));font-weight:700;color:rgba(230,87,99,.75);text-align:center;line-height:1.65;">Track her story in<br><span style="color:rgba(230,87,99,.95);font-weight:900;">Story → Characters</span></div><<elseif _talkLockedReason === "condition">><div style="font-size:calc(28px + var(--font-boost,0px));">🔒</div><div style="font-size:calc(16px + var(--font-boost,0px));font-weight:900;color:rgba(255,255,255,.92);text-align:center;line-height:1.6;letter-spacing:.01em;">Something is missing before this conversation can happen.</div><<if _talkRule.conditionHint>><div style="font-size:calc(14px + var(--font-boost,0px));font-weight:700;color:rgba(230,87,99,.75);text-align:center;line-height:1.65;"><<= _talkRule.conditionHint>></div><</if>><<else>><div style="font-size:calc(28px + var(--font-boost,0px));">🕐</div><div style="font-size:calc(16px + var(--font-boost,0px));font-weight:900;color:rgba(255,255,255,.92);text-align:center;line-height:1.6;letter-spacing:.01em;"><<= _npc.name || "This character" >> is only available at a <span style="color:rgb(230,87,99);">specific time</span>.</div><<if _talkRule>><div style="font-size:calc(15px + var(--font-boost,0px));font-weight:900;color:rgb(230,87,99);text-align:center;letter-spacing:.04em;">🕐 <<= _talkRule.times.map(function(t){return ["Morning","Noon","Afternoon","Night"][t];}).join(" · ")>></div><</if>><div style="font-size:calc(14px + var(--font-boost,0px));font-weight:700;color:rgba(230,87,99,.75);text-align:center;line-height:1.65;">Check her profile in<br><span style="color:rgba(230,87,99,.95);font-weight:900;">Story → Characters</span></div><</if>><div onclick="document.getElementById('iMenu-talk-locked-overlay').style.display='none';" style="margin-top:4px;padding:12px 36px;border-radius:10px;border:1px solid rgba(230,87,99,.40);background:rgba(230,87,99,.12);color:rgb(230,87,99);font-weight:950;font-size:calc(14px + var(--font-boost,0px));letter-spacing:.14em;text-transform:uppercase;cursor:pointer;">UNDERSTOOD</div></div></div>
<div class="iMenu-arc"><div class="iMenu-arc-left"><span class="iMenu-arc-name"><<= _npc.name || "Unknown" >></span><span class="iMenu-arc-sub">Corruption Level</span></div><div class="iMenu-arc-right"><span class="iMenu-arc-num"><<= _npc.lvl>></span><span class="iMenu-arc-sep">/</span><span class="iMenu-arc-max">6</span></div></div><div class="BottomUiBarCustom"><<BottomButton "Action">><<if _lvl >= 0>><<if _noSleep>><<link "🌙 Corrupt">><</link>><script>(function(){var links=document.querySelectorAll('.BottomUiBarCustom a');links.forEach(function(l){if(l.textContent.trim()==='🌙 Corrupt'){l.addEventListener('click',function(e){e.preventDefault();e.stopPropagation();var ov=document.getElementById('iMenu-sleep-locked-overlay');if(ov)ov.style.display='flex';});}});})();</script><<elseif _noPP>><<link "💫 Corrupt">><</link>><script>(function(){var links=document.querySelectorAll('.BottomUiBarCustom a');links.forEach(function(l){if(l.textContent.trim()==='💫 Corrupt'){l.addEventListener('click',function(e){e.preventDefault();e.stopPropagation();var ov=document.getElementById('iMenu-pp-locked-overlay');if(ov)ov.style.display='flex';});}});})();</script><<elseif _talkLocked>><<link "🔒 Corrupt">><</link>><script>(function(){var links=document.querySelectorAll('.BottomUiBarCustom a');links.forEach(function(l){if(l.textContent.trim()==='🔒 Corrupt'){l.addEventListener('click',function(e){e.preventDefault();e.stopPropagation();var ov=document.getElementById('iMenu-talk-locked-overlay');if(ov)ov.style.display='flex';});}});})();</script><<else>><<link "🧠 Corrupt">><<set $ActiveNPC = _npc>><<goto $PassTalk>><</link>><</if>>/*<<link "🎁 Gift">><<set $ActiveNPC = _npc>><<goto "Interact.Gift">><</link>>*/<</if>><<if _npc.sex == "F" or _npc.trans == true>><<if _npc.lvl >= 2>><<link "🔞 Grope">><<set $ActiveNPC = _npc>><<goto "Interact.Grope">><</link>><</if>><<if _npc.lvl >= 3>><<if $InteractInInterior == true or $Corruption.city >= 4>><<link "🔞 Handjob">><<set $ActiveNPC = _npc>><<goto "Interact.Handjob">><</link>><<elseif $InteractInInterior == false>><<link "🔒 Handjob">><</link>><</if>><<if _npc.lvl >= 4>><<if $InteractInInterior == true or $Corruption.city >= 4>><<link "🔞 Blowjob">><<set $ActiveNPC = _npc>><<goto "Interact.Blowjob">><</link>><<elseif $InteractInInterior == false>><<link "🔒 Blowjob">><</link>><</if>><<if _npc.lvl >= 5>><<if _npc.sex == "F" or _npc.futa == true>><<if $InteractInInterior == true or $Corruption.city >= 4>><<link "🔞 Pussy">><<set $ActiveNPC = _npc>><<goto "Interact.Pussy">><</link>><<elseif $InteractInInterior == false>><<link "🔒 Pussy">><</link>><</if>><</if>><<if $InteractInInterior == true or $Corruption.city >= 4>><<link "🔞 Anal">><<set $ActiveNPC = _npc>><<goto "Interact.Anal">><</link>><<elseif $InteractInInterior == false>><<link "🔒 Anal">><</link>><</if>><</if>><</if>><</if>><</if>><</BottomButton>></div><</if>><</if>><style>
.iMenu-error{padding:12px;border-radius:10px;background:rgba(255,255,255,.04);border:1px solid rgba(255,255,255,.08);color:rgba(255,255,255,.72);font-size:calc(14px + var(--font-boost,0px));font-weight:700;}
.iMenu-arc{display:flex;align-items:center;justify-content:space-between;padding:10px 14px;border-radius:12px;background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.07);margin-bottom:10px;}
.iMenu-arc-left{display:flex;flex-direction:column;gap:2px;}
.iMenu-arc-name{font-size:calc(24px + var(--font-boost,0px));font-weight:950;color:rgba(255,255,255,.92);letter-spacing:.02em;}
.iMenu-arc-sub{font-size:calc(12px + var(--font-boost,0px));font-weight:900;letter-spacing:.12em;text-transform:uppercase;color:rgba(255,255,255,.60);}
.iMenu-arc-right{display:flex;align-items:baseline;gap:3px;}
.iMenu-arc-num{font-size:calc(24px + var(--font-boost,0px));font-weight:950;color:rgb(230,87,99);line-height:1;}
.iMenu-arc-sep{font-size:calc(16px + var(--font-boost,0px));font-weight:700;color:rgba(255,255,255,.50);}
.iMenu-arc-max{font-size:calc(16px + var(--font-boost,0px));font-weight:700;color:rgba(255,255,255,.50);}
</style><</widget>>
--------------------------------------------------------------------------
<<widget "Gift">><<set _npc = $args[0]>><<if !_npc or !_npc.id>><p>Invalid NPC.</p><<return>><</if>><div class="giftPanel"><div class="gift-header"><div class="gift-title">🎁 Give a gift</div><div class="gift-to">to <span class="gift-npc-name"><<= _npc.name || _npc.id >></span></div></div><<set _hasGift = false>><<for _gid, _gift range $GiftItemsList>><<set _item = $Inventory[_gid]>><<if _item>><<set _hasGift = true>><div class="gift-row"><div class="gift-thumb"><<if _item.img>><img @src="_item.img"><<else>><span class="gift-no-img">?</span><</if>></div><div class="gift-info"><div class="gift-name"><<= _item.qty>>× <<= _item.name || _gid >></div><div class="gift-stats"><span class="gift-aff">❤️ +<<= _gift.aff || 0 >></span><span class="gift-cor">🖤 +<<= _gift.cor || 0 >></span></div></div><div class="gift-action"><<capture _gid _gift>><<link "Give">><<set _npc.aff += (_gift.aff || 0)>><<set _npc.cor += (_gift.cor || 0)>><<set _tmpGid = _gid>><<run (function(){const gid=State.temporary.tmpGid;const inv=State.variables.Inventory||{};const it=inv[gid];if(it==null){return;}if(typeof it==="number"){const q=it-1;if(q>0)inv[gid]=q;else delete inv[gid];return;}if(Object.prototype.hasOwnProperty.call(it,"qty")){it.qty=Math.max(0,(Number(it.qty)||0)-1);if(it.qty<=0)delete inv[gid];return;}if(Object.prototype.hasOwnProperty.call(it,"quantity")){it.quantity=Math.max(0,(Number(it.quantity)||0)-1);if(it.quantity<=0)delete inv[gid];return;}delete inv[gid];})()>><<Refresh>><</link>><</capture>></div></div><</if>><</for>><<if !_hasGift>><<InformationUiPopUp "Gift">>No available gifts.<</InformationUiPopUp>><</if>></div><style>
.giftPanel{width:100%;font-family:inherit;}
.gift-header{display:flex;align-items:baseline;gap:8px;padding:0 0 12px 0;border-bottom:1px solid rgba(255,255,255,.07);margin-bottom:14px;}
.gift-title{font-size:18px;font-weight:950;color:rgba(255,255,255,.95);letter-spacing:-.01em;}
.gift-to{font-size:12px;font-weight:700;color:rgba(255,255,255,.40);}
.gift-npc-name{color:rgba(230,87,99,.85);font-weight:900;}
.gift-row{display:flex;align-items:center;gap:12px;padding:10px;border-radius:12px;background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.07);margin-bottom:8px;transition:background .10s,border-color .10s;}
.gift-row:hover{background:rgba(255,255,255,.05);border-color:rgba(255,255,255,.10);}
.gift-thumb{flex:0 0 56px;width:56px;height:56px;border-radius:10px;overflow:hidden;background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.08);display:flex;align-items:center;justify-content:center;}
.gift-thumb img{width:56px!important;height:56px!important;min-width:56px!important;min-height:56px!important;max-width:none!important;max-height:none!important;object-fit:cover!important;object-position:center!important;display:block!important;margin:0!important;}
.gift-no-img{font-size:18px;color:rgba(255,255,255,.25);font-weight:900;}
.gift-info{flex:1 1 auto;min-width:0;}
.gift-name{font-size:13px;font-weight:900;color:rgba(255,255,255,.88);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin-bottom:5px;}
.gift-stats{display:flex;gap:8px;}
.gift-aff{font-size:11px;font-weight:800;color:rgba(255,120,140,.85);}
.gift-cor{font-size:11px;font-weight:800;color:rgba(180,120,255,.75);}
.gift-action .link-internal{all:unset;padding:7px 16px;border-radius:8px;background:rgba(230,87,99,.10);border:1px solid rgba(230,87,99,.25);color:rgba(230,87,99,.90);font-size:11px;font-weight:950;letter-spacing:.06em;cursor:pointer;transition:background .10s,border-color .10s,transform .10s;display:inline-block;}
.gift-action .link-internal:hover{background:rgba(230,87,99,.18);border-color:rgba(230,87,99,.45);transform:translateY(-1px);}
.gift-action .link-internal:active{transform:scale(.96);}
</style><</widget>>
--------------------------------------------------------------------------
/* <<TalkMC "Text">> */
<<widget "TalkMC">><<set _text = $args[0]>><<set _border = ($MCPlayer && $MCPlayer.color) ? $MCPlayer.color : "#ffffff">><<set _img = ($MCPlayer && $MCPlayer.img) ? $MCPlayer.img.replace(/\\/g,"/") : "">><style>
.talkmc-wrap{display:flex;align-items:flex-start;border-radius:8px;padding:clamp(8px,1.2vw,12px);background:rgba(8,8,8,.50);color:#fff;gap:clamp(8px,1vw,12px);}
.talkmc-avatar{width:clamp(36px,5vw,60px);height:clamp(36px,5vw,60px);border-radius:8px;flex-shrink:0;display:block;background-size:cover;background-position:center;background-repeat:no-repeat;}
.talkmc-body{flex:1;min-width:0;}
.talkmc-name{font-weight:bold;margin-bottom:.25rem;font-size:calc(16px + var(--font-boost,0px));}
.talkmc-text{font-size:calc(16px + var(--font-boost,0px));}
</style><<='<div class="talkmc-wrap" style="border:1px solid '+ _border +';">'
+ '<span class="talkmc-avatar"'
+ ( _img ? ' style="background-image:url(\''+ _img +'\')"' : '' )
+ '></span>'
+ '<div class="talkmc-body">'
+ '<div class="talkmc-name">'+ ($MCPlayer.firstname || '') +' '+ ($MCPlayer.lastname || '') +' <em>(You)</em></div>'
+ '<div class="talkmc-text">'+ _text +'</div>'
+ '</div>'
+ '</div>'
>><</widget>>
/* <<TalkNPC $NPCLandlady "Text">> */
<<widget "TalkNPC">><<set _npc = $args[0]>><<set _text = $args[1]>><<if !_npc>><<= '<div style="border:1px solid #f00;border-radius:8px;padding:.5rem;background:rgba(8,8,8,.50);color:#fff;font-size:calc(16px + var(--font-boost,0px));"><em>NPC not found.</em></div>' >>
<<else>><<set _border = (_npc.color || "#ffffff")>><<set _img = (_npc.img ? _npc.img.replace(/\\/g,"/") : "")>><style>
.talknpc-wrap{display:flex;align-items:flex-start;border-radius:8px;padding:clamp(8px,1.2vw,12px);background:rgba(8,8,8,.50);color:#fff;gap:clamp(8px,1vw,12px);}
.talknpc-avatar{width:clamp(36px,5vw,60px);height:clamp(36px,5vw,60px);border-radius:8px;flex-shrink:0;display:block;background-size:cover;background-position:center;background-repeat:no-repeat;}
.talknpc-body{flex:1;min-width:0;}
.talknpc-name{font-weight:bold;margin-bottom:.25rem;font-size:calc(16px + var(--font-boost,0px));}
.talknpc-text{font-size:calc(16px + var(--font-boost,0px));}
</style><<=
'<div class="talknpc-wrap" style="border:1px solid '+ _border +';">'
+ '<span class="talknpc-avatar"'
+ ( _img ? ' style="background-image:url(\''+ _img +'\')"' : '' )
+ '></span>'
+ '<div class="talknpc-body">'
+ '<div class="talknpc-name">'+ (_npc.name || 'NPC') +' <em>('+ _npc.role +')</em></div>'
+ '<div class="talknpc-text">'+ _text +'</div>'
+ '</div>'
+ '</div>'
>><</if>><</widget>>
/* <<TalkRandom "Display Name" "img/path.jpg" "Text">> */
<<widget "TalkRandom">><<set _name = $args[0]>><<set _img = (typeof $args[1] === "string" ? $args[1] : String($args[1] || "")).replace(/\\/g,"/")>><<set _text = $args[2]>><<set _border = ($NPCRandom && $NPCRandom.color) ? $NPCRandom.color : "#ffffff">><style>
.talkrnd-wrap{display:flex;align-items:flex-start;border-radius:8px;padding:clamp(8px,1.2vw,12px);background:rgba(8,8,8,.50);color:#fff;gap:clamp(8px,1vw,12px);}
.talkrnd-avatar{width:clamp(36px,5vw,60px);height:clamp(36px,5vw,60px);border-radius:8px;flex-shrink:0;display:block;background-size:cover;background-position:center;background-repeat:no-repeat;}
.talkrnd-body{flex:1;min-width:0;}
.talkrnd-name{font-weight:bold;margin-bottom:.25rem;font-size:calc(16px + var(--font-boost,0px));}
.talkrnd-text{font-size:calc(16px + var(--font-boost,0px));}
</style><<=
'<div class="talkrnd-wrap" style="border:1px solid '+ _border +';">'
+ '<span class="talkrnd-avatar"'
+ ( _img ? ' style="background-image:url(\''+ _img +'\')"' : '' )
+ '></span>'
+ '<div class="talkrnd-body">'
+ '<div class="talkrnd-name">'+ (_name || 'NPC') +'</div>'
+ '<div class="talkrnd-text">'+ _text +'</div>'
+ '</div>'
+ '</div>'
>><</widget>>
--------------------------------------------------------------------------
<<widget "Interact">><<set _npc = $args[0]>><<if !_npc>><div class="npcCard-error">NPC not found.</div><<else>><<set _img = (_npc.img ? _npc.img.replace(/\\/g,"/") : "")>><<set _name = (_npc.name || "NPC")>><<set _role = (_npc.role || "NPC")>><<set _color = (_npc.color || "#e65763")>><<set _pass = _npc.id + ".interact">><<= '<a href="javascript:void(0)" onclick="(function(){var S=window.SugarCube||window;S.State.variables.ReturnTo=S.State.passage;(S.Engine||Engine).play(\''+ _pass.replace(/\'/g,"\\\'") +'\');})()" class="npcCard-link"><div class="npcCard"><div class="npcCard-bg" style="background:'+_color+' !important;"></div>'+(_img?'<div class="npcCard-thumb"><img src="'+_img+'" alt="'+_name+'" style="width:56px!important;height:56px!important;min-width:56px!important;min-height:56px!important;max-width:none!important;max-height:none!important;object-fit:cover!important;object-position:center top!important;display:block!important;margin:0!important;"></div>':'<div class="npcCard-thumb npcCard-thumb-empty">?</div>')+'<div class="npcCard-body"><div class="npcCard-name">'+_name+'</div><div class="npcCard-role">'+_role+'</div></div><div class="npcCard-arrow">→</div></div></a>'>><</if>><style>.npcCard-error{padding:10px 14px;border-radius:10px;background:rgba(255,255,255,.04);border:1px solid rgba(255,255,255,.08);color:rgba(255,255,255,.60);font-size:calc(14px + var(--font-boost,0px));font-weight:700;}
.npcCard-link{text-decoration:none!important;display:block!important;margin-bottom:8px;}
.npcCard{position:relative;display:flex;align-items:center;gap:clamp(8px,1.2vw,12px);border-radius:12px;padding:clamp(8px,1.2vw,10px) clamp(10px,1.5vw,14px);overflow:hidden;border:1px solid rgba(255,255,255,.10);transition:border-color .12s,transform .10s;}
.npcCard-link:hover .npcCard{border-color:rgba(255,255,255,.22);transform:translateY(-1px);}
.npcCard-link:active .npcCard{transform:scale(.99);}
.npcCard-bg{position:absolute;inset:0;opacity:.20;z-index:0;}
.npcCard-thumb{position:relative;z-index:1;flex:0 0 clamp(44px,6vw,56px);width:clamp(44px,6vw,56px);height:clamp(44px,6vw,56px);border-radius:10px;overflow:hidden;border:1px solid rgba(255,255,255,.12);background:rgba(255,255,255,.06);}
.npcCard-thumb-empty{display:flex;align-items:center;justify-content:center;font-size:calc(18px + var(--font-boost,0px));color:rgba(255,255,255,.25);font-weight:900;}
.npcCard-body{position:relative;z-index:1;flex:1;min-width:0;}
.npcCard-name{font-size:calc(16px + var(--font-boost,0px));font-weight:950;color:rgba(255,255,255,.92);margin-bottom:3px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
.npcCard-role{font-size:calc(12px + var(--font-boost,0px));font-weight:800;color:rgba(255,255,255,.55);letter-spacing:.08em;text-transform:uppercase;}
.npcCard-arrow{position:relative;z-index:1;font-size:calc(14px + var(--font-boost,0px));color:rgba(255,255,255,.30);transition:color .12s,transform .12s;}
.npcCard-link:hover .npcCard-arrow{color:rgba(255,255,255,.70);transform:translateX(3px);}
</style><</widget>>
--------------------------------------------------------------------------
<<widget "Refresh">>
<<run (function(){
var dr = window.DialogRefresh;
var wasDialogOpen = dr && dr.isOpen();
if (window.PageRefresh) {
PageRefresh.capture();
PageRefresh.requestRestore();
}
if (wasDialogOpen) {
dr.captureScrollNow();
try { Dialog.close(); } catch (e) {}
}
setTimeout(function () {
SugarCube.Engine.show(SugarCube.State.passage, null, "replace");
if (wasDialogOpen) {
setTimeout(function () {
dr.reopen();
}, 0);
}
}, 0);
})()>>
<</widget>>
--------------------------------------------------------------------------
<<widget "CheatMenu">><<OpenHubMenu "SupportMenu">><</widget>>
--------------------------------------------------------------------------
<<widget "QuestStory">><<OpenHubMenu "QuestMenu">><</widget>>
--------------------------------------------------------------------------
<<widget "AchievementsMenu">><<OpenHubMenu "AchievementsMenu">><</widget>>
--------------------------------------------------------------------------
<<widget "SupportMenu">><<OpenHubMenu "SupportMenu">><</widget>>
--------------------------------------------------------------------------
<<widget "CreditsMenu">><<OpenHubMenu "SupportMenu">><</widget>>
--------------------------------------------------------------------------
<<widget "SavesMenu">><<OpenHubMenu "SavesMenu">><</widget>>
--------------------------------------------------------------------------
<<widget "Restart">><button onclick="SugarCube.Engine.restart()">Restart</button><</widget>>
<<widget "ReturnTo">><<if !$ReturnTo or $ReturnTo is "">><<set $ReturnTo = "MCBedroom">><</if>><<link "↩️ Return">><<goto $ReturnTo>><<set $ReturnTo = "">><</link>><</widget>>
<<widget "ReturnToGoto">><<if !$ReturnTo or $ReturnTo is "">><<set $ReturnTo = "MCBedroom">><</if>><<goto $ReturnTo>><<set $ReturnTo = "">><</widget>>
<<widget "SetReturnTo">><<run (function(){var S=window.SugarCube||window;S.State.variables.ReturnTo=S.State.passage;})()>><</widget>>
--------------------------------------------------------------------------
<<widget "MailReturnTo">><<if !$MailReturnTo or $MailReturnTo is "">><<set $MailReturnTo = "MCBedroom">><</if>><<link "↩️ Return">><<goto $MailReturnTo>><<set $ReturnTo = "">><</link>><</widget>>
<<widget "SetMailReturnTo">><<run (function(){var S=window.SugarCube||window;S.State.variables.MailReturnTo=S.State.passage;})()>><</widget>>
--------------------------------------------------------------------------
/* <<Sleeping $NPCName>> */
<<widget "Sleeping">><<set _npc = $args[0]>><<if !_npc>><<= '<div style="border:1px solid #f00 !important;border-radius:8px !important;padding:.5rem !important;background:#111 !important;color:#fff !important;"><em style="color:#fff !important;">NPC not found.</em></div>'>><<else>><<set _random = random(16)>><<passagebg>><<if _random == 0>><img src="assets/img/character/sleep/01.jpg"/><<elseif _random == 1>><img src="assets/img/character/sleep/02.jpg"/><<elseif _random == 2>><img src="assets/img/character/sleep/03.jpg"/><<elseif _random == 3>><img src="assets/img/character/sleep/04.jpg"/><<elseif _random == 4>><img src="assets/img/character/sleep/05.jpg"/><<elseif _random == 5>><img src="assets/img/character/sleep/06.jpg"/><<elseif _random == 6>><img src="assets/img/character/sleep/07.jpg"/><<elseif _random == 7>><img src="assets/img/character/sleep/08.jpg"/><<elseif _random == 8>><img src="assets/img/character/sleep/09.jpg"/><<elseif _random == 9>><img src="assets/img/character/sleep/10.jpg"/><<elseif _random == 10>><img src="assets/img/character/sleep/11.jpg"/><<elseif _random == 11>><img src="assets/img/character/sleep/12.jpg"/><<elseif _random == 12>><img src="assets/img/character/sleep/13.jpg"/><<elseif _random == 13>><img src="assets/img/character/sleep/14.jpg"/><<elseif _random == 14>><img src="assets/img/character/sleep/15.jpg"/><<elseif _random == 15>><img src="assets/img/character/sleep/16.jpg"/><<elseif _random == 16>><img src="assets/img/character/sleep/17.jpg"/><</if>><</passagebg>><<if _random == 0>><img src="assets/img/character/sleep/01.jpg"/><<elseif _random == 1>><img src="assets/img/character/sleep/02.jpg"/><<elseif _random == 2>><img src="assets/img/character/sleep/03.jpg"/><<elseif _random == 3>><img src="assets/img/character/sleep/04.jpg"/><<elseif _random == 4>><img src="assets/img/character/sleep/05.jpg"/><<elseif _random == 5>><img src="assets/img/character/sleep/06.jpg"/><<elseif _random == 6>><img src="assets/img/character/sleep/07.jpg"/><<elseif _random == 7>><img src="assets/img/character/sleep/08.jpg"/><<elseif _random == 8>><img src="assets/img/character/sleep/09.jpg"/><<elseif _random == 9>><img src="assets/img/character/sleep/10.jpg"/><<elseif _random == 10>><img src="assets/img/character/sleep/11.jpg"/><<elseif _random == 11>><img src="assets/img/character/sleep/12.jpg"/><<elseif _random == 12>><img src="assets/img/character/sleep/13.jpg"/><<elseif _random == 13>><img src="assets/img/character/sleep/14.jpg"/><<elseif _random == 14>><img src="assets/img/character/sleep/15.jpg"/><<elseif _random == 15>><img src="assets/img/character/sleep/16.jpg"/><<elseif _random == 16>><img src="assets/img/character/sleep/17.jpg"/><</if>>
<<TalkNPC _npc "<em>….is currently sleeping….</em>">><</if>><</widget>>
--------------------------------------------------------------------------
/* <<Shower $NPCName>> */
<<widget "Shower">><<set _npc = $args[0]>><<if !_npc>><<= '<div style="border:1px solid #f00 !important;border-radius:8px !important;padding:.5rem !important;background:#111 !important;color:#fff !important;"><em style="color:#fff !important;">NPC not found.</em></div>'>><<else>><<if _npc.lvl >= 0>><<set _random = random(6)>><<if _random == 0>><img src="assets/img/character/shower/1/01.webp"/><<elseif _random == 1>><img src="assets/img/character/shower/1/02.webp"/><<elseif _random == 2>><img src="assets/img/character/shower/1/03.webp"/><<elseif _random == 3>><img src="assets/img/character/shower/1/04.webp"/><<elseif _random == 4>><img src="assets/img/character/shower/1/05.webp"/><<elseif _random == 5>><img src="assets/img/character/shower/1/06.webp"/><<elseif _random == 6>><img src="assets/img/character/shower/1/07.webp"/><</if>>
<<TalkNPC _npc "<em>....is currently taking a shower....</em>">><</if>>
<<if _npc.lvl >= 2>><<set _random = random(8)>><<if _random == 0>><img src="assets/img/character/shower/2/01.webp"/><<elseif _random == 1>><img src="assets/img/character/shower/2/02.webp"/><<elseif _random == 2>><img src="assets/img/character/shower/2/03.webp"/><<elseif _random == 3>><img src="assets/img/character/shower/2/04.webp"/><<elseif _random == 4>><img src="assets/img/character/shower/2/05.webp"/><<elseif _random == 5>><img src="assets/img/character/shower/2/06.webp"/><<elseif _random == 6>><img src="assets/img/character/shower/2/07.webp"/><<elseif _random == 7>><img src="assets/img/character/shower/2/08.webp"/><<elseif _random == 8>><img src="assets/img/character/shower/2/09.webp"/><</if>>
<<TalkNPC _npc "Oh, look who's here... 👀">><</if>>
<<if _npc.lvl >= 4>><<set _random = random(7)>><<if _random == 0>><img src="assets/img/character/shower/3/01.webp"/><<elseif _random == 1>><img src="assets/img/character/shower/3/02.webp"/><<elseif _random == 2>><img src="assets/img/character/shower/3/03.webp"/><<elseif _random >= 3>><img src="assets/img/character/shower/3/04.webp"/><<elseif _random == 4>><img src="assets/img/character/shower/3/05.webp"/><<elseif _random == 5>><img src="assets/img/character/shower/3/06.webp"/><<elseif _random == 6>><img src="assets/img/character/shower/3/07.webp"/><<elseif _random == 7>><img src="assets/img/character/shower/3/08.webp"/><</if>>
<<TalkNPC _npc "Oh yes! go ahead <<=$MCPlayer.firstname>>, harder!">>
<<TalkMC "If that’s what you want, let me help you">>
<<Interact _npc>><</if>><</if>><</widget>>
--------------------------------------------------------------------------
<<widget "PitScoreboard">><<run setup.pit.ensureLadder()>><<set _rows=setup.pit.getSorted()>><<set _playerRank=0>><<for _i=0;_i<_rows.length;_i++>><<if _rows[_i].npc.id===setup.pit.playerId>><<set _playerRank=_i+1>><</if>><</for>><div class="pitBoard"><div class="pitBoard-header"><div class="pitBoard-title">🎯 The Pit — Scoreboard</div><div class="pitBoard-meta"><span class="pitBoard-count"><<= _rows.length>> fighters</span><<if _playerRank>><span class="pitBoard-yourrank">Your rank: #<<= _playerRank>></span><</if>></div></div><div class="pitBoard-table-wrap"><table class="pitBoard-table"><thead><tr><th>Rank</th><th>Fighter</th><th>ELO</th><th>W / L</th><th>WR</th><th>Fit</th><th>HP</th><th>Style</th></tr></thead><tbody><<for _i=0;_i<_rows.length;_i++>><<set _r=_rows[_i]>><<set _rank=Math.floor(_i+1)>><<set _elo=Math.round(+_r.rec.elo||0)>><<set _lvl=setup.pit.eloToLevel(_elo)>><<set _st=setup.pit.computeStats(_r.npc,_lvl)>><<set _w=+_r.rec.w||0>><<set _l=+_r.rec.l||0>><<set _wr=(_w+_l>0)?Math.round((_w/(_w+_l))*100):0>><<set _isPlayer=(_r.npc.id===setup.pit.playerId)>><<set _styleLabel=_isPlayer?"—":(_st.style||"—")>><tr class="pitBoard-row<<if _isPlayer>> pitBoard-row-player<</if>>"><td class="pitBoard-rank"><<if _rank==1>>🥇<<elseif _rank==2>>🥈<<elseif _rank==3>>🥉<<else>><<= String(_rank)>><</if>></td><td class="pitBoard-name"><<= _r.npc.name>></td><td class="pitBoard-elo"><<= _elo>></td><td class="pitBoard-wl"><span class="pitBoard-w"><<= _w>>W</span><span class="pitBoard-sep">/</span><span class="pitBoard-l"><<= _l>>L</span></td><td class="pitBoard-wr"><<= _wr>>%</td><td class="pitBoard-stat"><<= _st.fitness>></td><td class="pitBoard-stat"><<= _st.hpMax>></td><td class="pitBoard-style"><<= _styleLabel>></td></tr><</for>></tbody></table></div></div><style>
.pitBoard{width:100%;max-width:860px;margin:0 auto;font-family:inherit;}
.pitBoard-header{display:flex;align-items:center;justify-content:space-between;padding:0 0 12px 0;border-bottom:1px solid rgba(255,255,255,.07);margin-bottom:14px;flex-wrap:wrap;gap:8px;}
.pitBoard-title{font-size:calc(24px + var(--font-boost,0px));font-weight:950;color:rgba(255,255,255,.95);letter-spacing:-.01em;}
.pitBoard-meta{display:flex;gap:8px;align-items:center;flex-wrap:wrap;}
.pitBoard-count{font-size:calc(12px + var(--font-boost,0px));font-weight:800;color:rgba(255,255,255,.80);letter-spacing:.08em;}
.pitBoard-yourrank{font-size:calc(12px + var(--font-boost,0px));font-weight:900;color:rgba(230,87,99,.95);padding:3px 9px;border-radius:999px;background:rgba(230,87,99,.10);border:1px solid rgba(230,87,99,.28);letter-spacing:.06em;}
.pitBoard-table-wrap{width:100%;overflow-x:auto;}
.pitBoard-table{width:100%;border-collapse:collapse;}
.pitBoard-table thead tr{border-bottom:2px solid rgba(255,255,255,.10);}
.pitBoard-table th{padding:8px 10px;font-size:calc(12px + var(--font-boost,0px));font-weight:900;letter-spacing:.12em;color:rgba(255,255,255,.80);text-transform:uppercase;text-align:left;white-space:nowrap;}
.pitBoard-row{border-bottom:1px solid rgba(255,255,255,.08);transition:background .10s;}
.pitBoard-row:nth-child(even){background:rgba(0,0,0,.55);}
.pitBoard-row:hover{background:rgba(0,0,0,.35);}
.pitBoard-row-player{background:rgba(230,87,99,.06)!important;border-bottom:1px solid rgba(230,87,99,.15)!important;}
.pitBoard-row-player:hover{background:rgba(230,87,99,.10)!important;}
.pitBoard-table td{padding:12px 10px;white-space:nowrap;vertical-align:middle;}
.pitBoard-rank{font-size:calc(16px + var(--font-boost,0px));font-weight:950;color:rgba(255,255,255,.90);width:40px;}
.pitBoard-name{font-size:calc(14px + var(--font-boost,0px));font-weight:900;color:rgba(255,255,255,.92);}
.pitBoard-row-player .pitBoard-name{color:rgba(230,87,99,.95);}
.pitBoard-elo{font-size:calc(14px + var(--font-boost,0px));font-weight:950;color:rgba(255,255,255,.90);}
.pitBoard-wl{display:flex;align-items:center;gap:4px;font-size:calc(13px + var(--font-boost,0px));font-weight:800;}
.pitBoard-w{color:rgba(46,204,113,.90);}
.pitBoard-sep{color:rgba(255,255,255,.35);}
.pitBoard-l{color:rgba(231,76,60,.85);}
.pitBoard-wr{font-size:calc(13px + var(--font-boost,0px));font-weight:900;color:rgba(255,255,255,.92);}
.pitBoard-stat{font-size:calc(13px + var(--font-boost,0px));font-weight:700;color:rgba(255,255,255,.90);}
.pitBoard-style{font-size:calc(12px + var(--font-boost,0px));font-weight:900;letter-spacing:.06em;color:rgba(255,255,255,.82);text-transform:uppercase;}
</style><</widget>>
--- --- --- ---
<<widget "PitBetting">><<run setup.pit.ensureBetState()>><<run setup.pit.ensureLadder()>><<set _B=$PitBets>><<if !_B.open or !_B.match>><<set _m=setup.pit.makeMatch()>><<if _m>><<run setup.pit.simulateCrowdBets(_m)>><<set $PitBets.open=true>><<set $PitBets.match=_m>><<set $PitBets.playerBet=null>><<set $PitBets.result=null>><<set $PitBets.lastPayout=0>><<set _B=$PitBets>><</if>><</if>><<set _m=_B.match>><<if !_m>><div class="pitBet"><div class="pitBet-header"><div class="pitBet-title">💵 The Pit — Betting</div></div><div class="pitBet-empty">No match available right now.</div></div><<return>><</if>><<set _aNpc=setup.pit.getNpcById(_m.aId)>><<set _bNpc=setup.pit.getNpcById(_m.bId)>><<if !_aNpc or !_bNpc>><div class="pitBet"><div class="pitBet-header"><div class="pitBet-title">💵 The Pit — Betting</div></div><div class="pitBet-empty">No match available.</div></div><<return>><</if>><<set _labelA="Bet on "+_aNpc.name>><<set _labelB="Bet on "+_bNpc.name>><<set _playerStake=_B.playerBet?_B.playerBet.stake:0>><<set _potAWithPlayer=_m.potA+(_B.playerBet&&_B.playerBet.pick===_m.aId?_playerStake:0)>><<set _potBWithPlayer=_m.potB+(_B.playerBet&&_B.playerBet.pick===_m.bId?_playerStake:0)>><<set _totalWithPlayer=_potAWithPlayer+_potBWithPlayer>><div class="pitBet"><div class="pitBet-header"><div class="pitBet-title">💵 The Pit — Betting</div><div class="pitBet-meta"><span class="pitBet-pill">👥 <<= _m.spectators>></span><span class="pitBet-pill">🎰 <<= _m.bettors>> bettors</span></div></div><div class="pitBet-matchcard"><div class="pitBet-fighters"><div class="pitBet-fighter"><div class="pitBet-fighter-name"><<= _aNpc.name>></div><div class="pitBet-fighter-odds">x<<= _m.oddsA.toFixed(2)>></div><div class="pitBet-fighter-pot">$<<= _potAWithPlayer>></div></div><div class="pitBet-vs">VS</div><div class="pitBet-fighter pitBet-fighter-right"><div class="pitBet-fighter-name"><<= _bNpc.name>></div><div class="pitBet-fighter-odds">x<<= _m.oddsB.toFixed(2)>></div><div class="pitBet-fighter-pot">$<<= _potBWithPlayer>></div></div></div><div class="pitBet-potrow"><span class="pitBet-potlabel">Total pot</span><span class="pitBet-potval">$<<= _totalWithPlayer>></span><<if _playerStake>0>><span class="pitBet-potsplit">includes your $<<= _playerStake>> bet</span><<else>><span class="pitBet-potsplit">crowd only</span><</if>></div><<if _m.isPlayerFight>><div class="pitBet-notice">This is your scheduled fight. Use the fight panel to confirm and start.</div><</if>></div><<if !_m.isPlayerFight>><<if _B.result>><<set _winNpc=setup.pit.getNpcById(_B.result.winner)>><div class="pitBet-result"><<if _B.playerBet>><<if _B.playerBet.pick is _B.result.winner>><div class="pitBet-result-outcome pitBet-result-win">Victory — <strong><<= _winNpc.name>></strong> wins</div><div class="pitBet-result-payout">You bet <strong>$<<= _B.playerBet.stake>></strong> and won <strong>$<<= _B.lastPayout>></strong> <span class="pitBet-result-net">(net +$<<= _B.lastPayout-_B.playerBet.stake>>)</span></div><<else>><div class="pitBet-result-outcome pitBet-result-loss">Defeat — <strong><<= _winNpc.name>></strong> wins</div><div class="pitBet-result-payout">You lost your <strong>$<<= _B.playerBet.stake>></strong> bet.</div><</if>><<else>><div class="pitBet-result-outcome">Winner: <strong><<= _winNpc.name>></strong></div><div class="pitBet-result-payout">You did not place a bet.</div><</if>></div><div class="pitBet-btnrow"><<button "New match">><<set $PitBets.open=false>><<set $PitBets.match=null>><<set $PitBets.playerBet=null>><<set $PitBets.result=null>><<set $PitBets.lastPayout=0>><<Refresh>><</button>></div><<else>><div class="pitBet-section"><div class="pitBet-section-title">Place your bet</div><div class="pitBet-betrow"><div class="pitBet-cashlabel">Cash available: <span class="pitBet-cashval">$<<= +$Money||0>></span></div><<textbox "_stake" "0">></div><<set _potentialA=_B.playerBet?0:setup.pit.estimatePayout(_m,_m.aId,1)>><<set _potentialB=_B.playerBet?0:setup.pit.estimatePayout(_m,_m.bId,1)>><div class="pitBet-btnrow"><<button _labelA>><<set _stake=Math.floor(+_stake||0)>><<set _maxStake=Math.floor(+$Money||0)>><<if _stake>0 and _stake<=_maxStake and !_B.playerBet>><<set $Money-=_stake>><<set $PitBets.playerBet={pick:_m.aId,stake:_stake}>><<Refresh>><</if>><</button>><<button _labelB>><<set _stake=Math.floor(+_stake||0)>><<set _maxStake=Math.floor(+$Money||0)>><<if _stake>0 and _stake<=_maxStake and !_B.playerBet>><<set $Money-=_stake>><<set $PitBets.playerBet={pick:_m.bId,stake:_stake}>><<Refresh>><</if>><</button>></div><<if _B.playerBet>><div class="pitBet-betplaced">Bet placed: <strong>$<<= _B.playerBet.stake>></strong> on <strong><<= setup.pit.getNpcById(_B.playerBet.pick).name>></strong> · est. payout <strong>$<<= setup.pit.estimatePayout(_m,_B.playerBet.pick,_B.playerBet.stake)>></strong><div class="pitBet-cancelbet"><<button "Cancel bet">><<set $Money+=_B.playerBet.stake>><<set $PitBets.playerBet=null>><<Refresh>><</button>></div></div><</if>><div class="pitBet-btnrow pitBet-btnrow-resolve"><<button "▶ Resolve match">><<set _res=setup.pit.resolveMatch(_m)>><<set $PitBets.result=_res>><<if $PitBets.playerBet>><<set _pb=$PitBets.playerBet>><<if _pb.pick is _res.winner>><<set _pay=setup.pit.payoutPlayer(_m,_pb.pick,_pb.stake)>><<set $PitBets.lastPayout=_pay.payout>><<set $Money+=_pay.payout>><<else>><<set $PitBets.lastPayout=0>><</if>><</if>><<run setup.pit.applyElo(_m.aId,_m.bId,_res.winner)>><<Refresh>><</button>></div></div><</if>><</if>></div><style>
.pitBet{width:100%;max-width:860px;margin:0 auto;font-family:inherit;}
.pitBet-header{display:flex;align-items:center;justify-content:space-between;padding:0 0 12px 0;border-bottom:1px solid rgba(255,255,255,.07);margin-bottom:14px;flex-wrap:wrap;gap:8px;}
.pitBet-title{font-size:calc(24px + var(--font-boost,0px));font-weight:950;color:rgba(255,255,255,.95);letter-spacing:-.01em;}
.pitBet-meta{display:flex;gap:6px;flex-wrap:wrap;}
.pitBet-pill{display:inline-flex;align-items:center;padding:4px 10px;border-radius:999px;background:rgba(0,0,0,.40);border:1px solid rgba(255,255,255,.08);font-size:calc(13px + var(--font-boost,0px));font-weight:800;color:rgba(255,255,255,.90);}
.pitBet-matchcard{padding:14px;border-radius:12px;background:rgba(0,0,0,.50);border:1px solid rgba(255,255,255,.08);margin-bottom:14px;}
.pitBet-fighters{display:grid;grid-template-columns:1fr 40px 1fr;align-items:center;gap:8px;margin-bottom:10px;}
.pitBet-fighter{display:flex;flex-direction:column;gap:3px;}
.pitBet-fighter-right{text-align:right;}
.pitBet-fighter-name{font-size:calc(16px + var(--font-boost,0px));font-weight:950;color:rgba(255,255,255,.92);letter-spacing:1px;}
.pitBet-fighter-odds{font-size:calc(14px + var(--font-boost,0px));font-weight:800;color:rgba(230,87,99,.90);}
.pitBet-fighter-pot{font-size:calc(13px + var(--font-boost,0px));font-weight:700;color:rgba(255,255,255,.80);}
.pitBet-vs{text-align:center;font-size:calc(14px + var(--font-boost,0px));font-weight:950;letter-spacing:.10em;color:rgba(255,255,255,.92);}
.pitBet-potrow{display:flex;align-items:center;gap:10px;padding-top:10px;border-top:1px solid rgba(255,255,255,.06);flex-wrap:wrap;}
.pitBet-potlabel{font-size:calc(12px + var(--font-boost,0px));font-weight:900;letter-spacing:.12em;color:rgba(255,255,255,.80);text-transform:uppercase;}
.pitBet-potval{font-size:calc(14px + var(--font-boost,0px));font-weight:950;color:rgba(255,255,255,.90);}
.pitBet-potsplit{font-size:calc(12px + var(--font-boost,0px));font-weight:700;color:rgba(255,255,255,.80);font-style:italic;}
.pitBet-notice{margin-top:10px;padding:8px 12px;border-radius:8px;background:rgba(230,87,99,.08);border:1px solid rgba(230,87,99,.20);font-size:calc(14px + var(--font-boost,0px));font-weight:700;color:rgba(230,87,99,.90);font-style:italic;}
.pitBet-section{margin-bottom:14px;}
.pitBet-section-title{font-size:calc(12px + var(--font-boost,0px));font-weight:900;letter-spacing:.12em;color:rgba(255,255,255,.80);text-transform:uppercase;margin-bottom:10px;}
.pitBet-betrow{display:flex;align-items:center;gap:12px;margin-bottom:10px;flex-wrap:wrap;}
.pitBet-cashlabel{font-size:calc(14px + var(--font-boost,0px));font-weight:700;color:rgba(255,255,255,.88);}
.pitBet-cashval{color:rgba(255,255,255,.92);font-weight:950;}
.pitBet-btnrow{display:flex;gap:8px;flex-wrap:wrap;margin-bottom:10px;}
.pitBet-btnrow button{all:unset;padding:8px 16px;border-radius:10px;background:rgba(0,0,0,.40);border:1px solid rgba(255,255,255,.10);color:rgba(255,255,255,.94);font-size:calc(14px + var(--font-boost,0px));font-weight:950;letter-spacing:1px;cursor:pointer;transition:background .10s,border-color .10s,transform .10s;}
.pitBet-btnrow button:hover{background:rgba(0,0,0,.30);border-color:rgba(255,255,255,.18);transform:translateY(-1px);}
.pitBet-btnrow button:active{transform:scale(.96);}
.pitBet-btnrow-resolve button{background:rgba(230,87,99,.10);border-color:rgba(230,87,99,.28);color:rgba(230,87,99,.95);}
.pitBet-btnrow-resolve button:hover{background:rgba(230,87,99,.18);border-color:rgba(230,87,99,.50);}
.pitBet-betplaced{padding:10px 12px;border-radius:8px;background:rgba(0,0,0,.45);border:1px solid rgba(255,255,255,.08);font-size:calc(14px + var(--font-boost,0px));font-weight:700;color:rgba(255,255,255,.90);margin-bottom:10px;display:flex;align-items:center;gap:10px;flex-wrap:wrap;justify-content:space-between;}
.pitBet-cancelbet button{padding:6px 12px!important;font-size:calc(12px + var(--font-boost,0px))!important;background:rgba(231,76,60,.10)!important;border-color:rgba(231,76,60,.25)!important;color:rgba(231,76,60,.90)!important;}
.pitBet-cancelbet button:hover{background:rgba(231,76,60,.18)!important;border-color:rgba(231,76,60,.45)!important;}
.pitBet-result{padding:14px;border-radius:12px;background:rgba(0,0,0,.50);border:1px solid rgba(255,255,255,.08);margin-bottom:12px;}
.pitBet-result-outcome{font-size:calc(16px + var(--font-boost,0px));font-weight:950;color:rgba(255,255,255,.92);margin-bottom:6px;}
.pitBet-result-win{color:rgba(46,204,113,.92);}
.pitBet-result-loss{color:rgba(231,76,60,.88);}
.pitBet-result-payout{font-size:calc(14px + var(--font-boost,0px));font-weight:700;color:rgba(255,255,255,.90);}
.pitBet-result-net{font-weight:900;color:rgba(46,204,113,.92);margin-left:4px;}
.pitBet-empty{padding:30px 0;text-align:center;color:rgba(255,255,255,.94);font-size:calc(14px + var(--font-boost,0px));font-weight:700;letter-spacing:.06em;}
</style><</widget>>
--- --- --- ---
<<widget "PitEnterFight">><<run setup.pit.ensureBetState()>><<run setup.pit.ensureLadder()>><<set _pf=$PitFight>><<set _heal=Math.floor(+$Heal||0)>><<set _canFight=_heal>=20>><div class="pitEnter"><<if !_pf or !_pf.pending>><div class="pitEnter-idle"><div class="pitEnter-desc">Take part in matches to climb the scoreboard. Win to earn money, reputation, and ELO. Loss heals you back to a minimum.</div><<if !_canFight>><div class="pitEnter-warn">⚠ You need at least 20 HP to enter the pit. Current: <<= _heal>> HP.</div><</if>><div class="pitEnter-btnrow"><<button "🥊 Enter the Pit">><<if _canFight and setup.pit.preparePlayerPitFight()>><<Refresh>><</if>><</button>></div></div><<else>><<set _m=_pf.match>><<set _a=setup.pit.getNpcById(_m.aId)>><<set _b=setup.pit.getNpcById(_m.bId)>><<set _playerEloRec=$PitLadder[setup.pit.playerId]>><<set _foeEloRec=$PitLadder[_m.bId]>><<set _playerElo=_playerEloRec?Math.round(+_playerEloRec.elo||500):500>><<set _foeElo=_foeEloRec?Math.round(+_foeEloRec.elo||500):500>><div class="pitEnter-card"><div class="pitEnter-card-header">Confirm fight</div><div class="pitEnter-fighters"><div class="pitEnter-fighter"><div class="pitEnter-fighter-name"><<= _a.name>></div><div class="pitEnter-fighter-elo">ELO <<= _playerElo>></div><div class="pitEnter-fighter-odds">x<<= _m.oddsA.toFixed(2)>></div></div><div class="pitEnter-vs">VS</div><div class="pitEnter-fighter pitEnter-fighter-right"><div class="pitEnter-fighter-name"><<= _b.name>></div><div class="pitEnter-fighter-elo">ELO <<= _foeElo>></div><div class="pitEnter-fighter-odds">x<<= _m.oddsB.toFixed(2)>></div></div></div><div class="pitEnter-meta"><span class="pitEnter-pill">👥 <<= _m.spectators>></span><span class="pitEnter-pill">🎰 <<= _m.bettors>> bettors</span><span class="pitEnter-pill">💰 $<<= _m.totalPot>> pot</span><span class="pitEnter-pill">🏆 ~$<<= setup.pit.fighterPurse(_m,true)>> if win</span></div><div class="pitEnter-btnrow"><<button "▶ Start fight">><<if setup.pit.startPreparedPitFight()>><<goto "FightThePit">><</if>><</button>><<button "Cancel">><<set $PitFight=null>><<set $PitCurrentOpponent=null>><<set $PitBets.open=false>><<set $PitBets.match=null>><<set $PitBets.playerBet=null>><<set $PitBets.result=null>><<set $PitBets.lastPayout=0>><<Refresh>><</button>></div></div><</if>></div><style>
.pitEnter{width:100%;max-width:860px;margin:0 auto;font-family:inherit;}
.pitEnter-idle{padding:16px;border-radius:12px;background:rgba(0,0,0,.50);border:1px solid rgba(255,255,255,.08);}
.pitEnter-desc{font-size:calc(14px + var(--font-boost,0px));font-weight:700;color:rgba(255,255,255,.94);line-height:1.5;font-style:italic;margin-bottom:14px;}
.pitEnter-warn{padding:8px 12px;border-radius:8px;background:rgba(231,76,60,.10);border:1px solid rgba(231,76,60,.28);font-size:calc(14px + var(--font-boost,0px));font-weight:800;color:rgba(231,76,60,.92);margin-bottom:14px;}
.pitEnter-card{padding:16px;border-radius:12px;background:rgba(0,0,0,.50);border:1px solid rgba(255,255,255,.08);}
.pitEnter-card-header{font-size:calc(12px + var(--font-boost,0px));font-weight:900;letter-spacing:.12em;color:rgba(255,255,255,.80);text-transform:uppercase;margin-bottom:14px;}
.pitEnter-fighters{display:grid;grid-template-columns:1fr 40px 1fr;align-items:center;gap:8px;margin-bottom:14px;}
.pitEnter-fighter{display:flex;flex-direction:column;gap:4px;}
.pitEnter-fighter-right{text-align:right;}
.pitEnter-fighter-name{font-size:calc(16px + var(--font-boost,0px));font-weight:950;color:rgba(255,255,255,.92);}
.pitEnter-fighter-elo{font-size:calc(13px + var(--font-boost,0px));font-weight:700;color:rgba(255,255,255,.80);letter-spacing:.06em;}
.pitEnter-fighter-odds{font-size:calc(14px + var(--font-boost,0px));font-weight:800;color:rgba(230,87,99,.90);}
.pitEnter-vs{text-align:center;font-size:calc(14px + var(--font-boost,0px));font-weight:950;letter-spacing:.10em;color:rgba(255,255,255,.35);}
.pitEnter-meta{display:flex;gap:6px;flex-wrap:wrap;margin-bottom:16px;padding-top:12px;border-top:1px solid rgba(255,255,255,.06);}
.pitEnter-pill{display:inline-flex;align-items:center;padding:4px 10px;border-radius:999px;background:rgba(0,0,0,.40);border:1px solid rgba(255,255,255,.08);font-size:calc(13px + var(--font-boost,0px));font-weight:800;color:rgba(255,255,255,.90);}
.pitEnter-btnrow{display:flex;gap:8px;flex-wrap:wrap;}
.pitEnter-btnrow button{all:unset;padding:9px 18px;border-radius:10px;background:rgba(0,0,0,.40);border:1px solid rgba(255,255,255,.10);color:rgba(255,255,255,.94);font-size:calc(14px + var(--font-boost,0px));font-weight:950;letter-spacing:1px;cursor:pointer;transition:background .10s,border-color .10s,transform .10s;}
.pitEnter-btnrow button:hover{background:rgba(0,0,0,.30);border-color:rgba(255,255,255,.18);transform:translateY(-1px);}
.pitEnter-btnrow button:active{transform:scale(.96);}
.pitEnter-btnrow button:first-of-type{background:rgba(230,87,99,.10);border-color:rgba(230,87,99,.28);color:rgba(230,87,99,.95);}
.pitEnter-btnrow button:first-of-type:hover{background:rgba(230,87,99,.18);border-color:rgba(230,87,99,.50);}
.pitBet-betrow input{background:rgba(0,0,0,.50)!important;border:1px solid rgba(255,255,255,.25)!important;border-radius:8px!important;padding:6px 12px!important;color:rgba(255,255,255,.98)!important;font-size:calc(14px + var(--font-boost,0px))!important;font-weight:800!important;width:110px!important;outline:none!important;}
.pitBet-betrow input:focus{border-color:rgba(230,87,99,.45)!important;background:rgba(0,0,0,.40)!important;}
</style><</widget>>
--------------------------------------------------------------------------
<<script>>
setup.pit=setup.pit||{};
setup.pit.playerId="pit_player";
setup.pit.playerName=function(){const V=State.variables;return String(V.PlayerName||V.Name||"You");};
setup.pit.ensurePlayerNpc=function(){
setup.pit.npcs=setup.pit.npcs||[];
const id=setup.pit.playerId;
let fit=Number(State.variables.Fitness);
if(!Number.isFinite(fit)) fit=0;
fit=Math.floor(fit);
for(let i=0;i<setup.pit.npcs.length;i++){
if(setup.pit.npcs[i].id===id){
setup.pit.npcs[i].name=setup.pit.playerName();
setup.pit.npcs[i].base=setup.pit.npcs[i].base||{};
setup.pit.npcs[i].base.fitness=fit;
if(setup.pit.npcs[i].base.style) delete setup.pit.npcs[i].base.style;
return;
}
}
setup.pit.npcs.push({id:id,name:setup.pit.playerName(),base:{fitness:fit}});
};
setup.pit.npcs=[
{id:"pit_nova",name:"NovaSlam",base:{fitness:24,style:"Brawler"}},
{id:"pit_wolf",name:"WolfStatic",base:{fitness:23,style:"Pressure Fighter"}},
{id:"pit_onyx",name:"OnyxVex",base:{fitness:22,style:"Pressure Fighter"}},
{id:"pit_orchid",name:"OrchidHex",base:{fitness:21,style:"Out-Fighter"}},
{id:"pit_moss",name:"MossCutter",base:{fitness:20,style:"All-Rounder"}},
{id:"pit_sable",name:"SableRift",base:{fitness:19,style:"All-Rounder"}},
{id:"pit_raven",name:"RavenByte",base:{fitness:18,style:"Counterpuncher"}},
{id:"pit_lynx",name:"LynxNeedle",base:{fitness:17,style:"Counterpuncher"}},
{id:"pit_koi",name:"KoiSignal",base:{fitness:16,style:"Out-Fighter"}},
{id:"pit_jade",name:"JadeSplice",base:{fitness:16,style:"All-Rounder"}},
{id:"pit_ember",name:"EmberPulse",base:{fitness:15,style:"Out-Fighter"}},
{id:"pit_ghost",name:"GhostGrin",base:{fitness:14,style:"Counterpuncher"}},
{id:"pit_viper",name:"ViperSyntax",base:{fitness:20,style:"Pressure Fighter"}},
{id:"pit_blade",name:"BladeKernel",base:{fitness:19,style:"Brawler"}},
{id:"pit_siren",name:"SirenLoop",base:{fitness:17,style:"Out-Fighter"}},
{id:"pit_talon",name:"TalonPatch",base:{fitness:18,style:"Counterpuncher"}},
{id:"pit_hollow",name:"HollowPing",base:{fitness:15,style:"All-Rounder"}},
{id:"pit_glitch",name:"GlitchHaze",base:{fitness:16,style:"Out-Fighter"}},
{id:"pit_oxide",name:"OxideKnock",base:{fitness:21,style:"Brawler"}},
{id:"pit_cobalt",name:"CobaltRush",base:{fitness:18,style:"All-Rounder"}},
{id:"pit_fang",name:"FangVector",base:{fitness:22,style:"Pressure Fighter"}},
{id:"pit_kraken",name:"KrakenByte",base:{fitness:20,style:"Brawler"}},
{id:"pit_warden",name:"WardenTrace",base:{fitness:19,style:"Counterpuncher"}},
{id:"pit_quartz",name:"QuartzFlick",base:{fitness:17,style:"All-Rounder"}},
{id:"pit_nitro",name:"NitroChoke",base:{fitness:23,style:"Brawler"}},
{id:"pit_prism",name:"PrismCrow",base:{fitness:16,style:"Out-Fighter"}},
{id:"pit_bishop",name:"BishopNull",base:{fitness:18,style:"Pressure Fighter"}},
{id:"pit_drift",name:"DriftPulse",base:{fitness:15,style:"Counterpuncher"}},
{id:"pit_marrow",name:"MarrowClaw",base:{fitness:21,style:"Pressure Fighter"}},
{id:"pit_vega",name:"VegaRuin",base:{fitness:17,style:"All-Rounder"}}
];
setup.pit.clamp=function(n,min,max){return(n<min?min:(n>max?max:n));};
setup.pit.rndInt=function(a,b){return Math.floor(Math.random()*(b-a+1))+a;};
setup.pit.rnd=function(a,b){return a+Math.random()*(b-a);};
setup.pit.styleMods={"Out-Fighter":{dodgeBias:+0.20,atkMul:-0.05,hpMul:-0.05},"Counterpuncher":{dodgeBias:+0.10,atkMul:+0.05,hpMul:-0.05},"Pressure Fighter":{dodgeBias:-0.10,atkMul:+0.10,hpMul:+0.10},"Brawler":{dodgeBias:-0.15,atkMul:+0.15,hpMul:+0.10},"All-Rounder":{dodgeBias:+0.00,atkMul:+0.00,hpMul:+0.00},Balanced:{dodgeBias:+0.00,atkMul:+0.00,hpMul:+0.00}};
setup.pit.eloToLevel=function(elo){elo=Math.round(+elo||0);if(elo>=900)return 5;if(elo>=700)return 4;if(elo>=500)return 3;if(elo>=300)return 2;return 1;};
setup.pit.computeStats=function(npc,lvl){
if(npc && npc.id===setup.pit.playerId){
const V=State.variables;
let fit=Number(V.Fitness);
if(!Number.isFinite(fit)) fit=0;
fit=Math.floor(fit);
let hpMax=Number(V.HealMax);
if(!Number.isFinite(hpMax)||hpMax<=0) hpMax=Number(V.Heal);
if(!Number.isFinite(hpMax)||hpMax<=0) hpMax=100;
hpMax=Math.floor(hpMax);
const atkMul=setup.pit.clamp(1+(fit*0.01),0.80,1.60);
const dodgeBias=setup.pit.clamp(0.25+(fit*0.005),0.10,0.85);
return{lvl:lvl,fitness:fit,atkMul:atkMul,dodgeBias:dodgeBias,hpMax:hpMax,style:""};
}
const baseFit=(npc&&npc.base&&Number.isFinite(+npc.base.fitness))?+npc.base.fitness:15;
const style=(npc&&npc.base&&npc.base.style)?String(npc.base.style):"Balanced";
const mod=setup.pit.styleMods[style]||setup.pit.styleMods.Balanced;
const fit=Math.round(baseFit+(lvl-1)*6);
const atkMul=setup.pit.clamp(1.00+(lvl-1)*0.06+(mod.atkMul||0),0.80,1.60);
const dodgeBias=setup.pit.clamp(0.50+(lvl-1)*0.03+(mod.dodgeBias||0),0.15,0.90);
const hpMax=Math.round(100*(1.00+(lvl-1)*0.10+(mod.hpMul||0)));
return{lvl:lvl,fitness:fit,atkMul:atkMul,dodgeBias:dodgeBias,hpMax:hpMax,style:style};
};
setup.pit.computePlayerStats=function(lvl){
return setup.pit.computeStats({id:setup.pit.playerId},lvl);
};
setup.pit.fixedSeeds={pit_nova:{elo:980,w:12,l:4},pit_wolf:{elo:955,w:11,l:5},pit_onyx:{elo:930,w:10,l:5},pit_orchid:{elo:890,w:9,l:6},pit_moss:{elo:860,w:9,l:7},pit_sable:{elo:835,w:8,l:7},pit_raven:{elo:805,w:8,l:8},pit_lynx:{elo:780,w:7,l:8},pit_koi:{elo:755,w:7,l:9},pit_jade:{elo:730,w:6,l:9},pit_ember:{elo:705,w:6,l:10},pit_ghost:{elo:680,w:5,l:10},pit_viper:{elo:920,w:10,l:6},pit_blade:{elo:875,w:9,l:7},pit_siren:{elo:740,w:6,l:9},pit_talon:{elo:810,w:8,l:8},pit_hollow:{elo:520,w:4,l:8},pit_glitch:{elo:610,w:5,l:9},pit_oxide:{elo:945,w:11,l:5},pit_cobalt:{elo:665,w:5,l:10},pit_fang:{elo:970,w:12,l:5},pit_kraken:{elo:845,w:8,l:7},pit_warden:{elo:795,w:7,l:8},pit_quartz:{elo:575,w:4,l:9},pit_nitro:{elo:995,w:13,l:4},pit_prism:{elo:455,w:3,l:8},pit_bishop:{elo:705,w:6,l:9},pit_drift:{elo:335,w:2,l:6},pit_marrow:{elo:905,w:10,l:6},pit_vega:{elo:255,w:1,l:4}};
setup.pit.ensureLadder=function(){
const V=State.variables;
if(!V.PitLadder)V.PitLadder={};
if(!V.PitMeta)V.PitMeta={};
setup.pit.ensurePlayerNpc();
if(V.PitMeta.ladderInit!==true){
setup.pit.npcs.forEach(n=>{
if(!V.PitLadder[n.id]){
const s=setup.pit.fixedSeeds[n.id]||{elo:500,w:0,l:0};
let e=Math.round(+s.elo||500);
if(e<100)e=100;
if(e>1000)e=1000;
V.PitLadder[n.id]={id:n.id,elo:e,w:Math.round(+s.w||0),l:Math.round(+s.l||0)};
}
});
V.PitMeta.ladderInit=true;
}
if(!V.PitLadder[setup.pit.playerId]){
V.PitLadder[setup.pit.playerId]={id:setup.pit.playerId,elo:500,w:0,l:0};
}
setup.pit.npcs.forEach(n=>{
if(!V.PitLadder[n.id]){
V.PitLadder[n.id]={id:n.id,elo:500,w:0,l:0};
}
});
};
setup.pit.getNpcById=function(id){const list=setup.pit.npcs||[];for(let i=0;i<list.length;i++){if(list[i].id===id)return list[i];}return null;};
setup.pit.getRecordById=function(id){const V=State.variables;if(!V.PitLadder||!V.PitLadder[id])return null;return V.PitLadder[id];};
setup.pit.getSorted=function(){
const V=State.variables;
setup.pit.ensureLadder();
const arr=setup.pit.npcs.map(n=>{const rec=V.PitLadder[n.id];return{npc:n,rec:rec};});
arr.sort((a,b)=>(b.rec.elo||0)-(a.rec.elo||0));
return arr;
};
setup.pit.computeSpectators=function(){
const V=State.variables;
let n=setup.pit.rndInt(25,50);
n-=setup.pit.rndInt(0,10);
if(+V.Time===3)n+=setup.pit.rndInt(25,50);
const rep=Math.max(0,+V.Reputation||0);
n+=Math.floor(rep*0.15);
if(n<5)n=5;
return n;
};
setup.pit.winProb=function(aId,bId){
const Va=setup.pit.getRecordById(aId)||{elo:500};
const Vb=setup.pit.getRecordById(bId)||{elo:500};
const ra=+Va.elo||500,rb=+Vb.elo||500;
const al=setup.pit.eloToLevel(ra),bl=setup.pit.eloToLevel(rb);
const aSt=setup.pit.computeStats(setup.pit.getNpcById(aId)||{id:aId},al);
const bSt=setup.pit.computeStats(setup.pit.getNpcById(bId)||{id:bId},bl);
const ratingA=ra+(aSt.fitness*6)+(aSt.atkMul*80)+(aSt.dodgeBias*60)+(aSt.hpMax*0.6);
const ratingB=rb+(bSt.fitness*6)+(bSt.atkMul*80)+(bSt.dodgeBias*60)+(bSt.hpMax*0.6);
const diff=ratingA-ratingB;
const p=1/(1+Math.pow(10,(-diff/400)));
return setup.pit.clamp(p,0.07,0.93);
};
setup.pit.ensureBetState=function(){const V=State.variables;if(!V.PitBets)V.PitBets={open:false,match:null,playerBet:null,result:null,lastPayout:0};};
setup.pit.makeMatch=function(){
const rows=setup.pit.getSorted().filter(r=>r.npc.id!==setup.pit.playerId);
if(rows.length<2)return null;
const pairs=[];
for(let i=0;i<rows.length;i++){
for(let j=i+1;j<rows.length;j++){
const a=rows[i].npc.id,b=rows[j].npc.id;
const ea=+rows[i].rec.elo||500,eb=+rows[j].rec.elo||500;
const d=Math.abs(ea-eb);
if(d<=120)pairs.push({aId:a,bId:b,diff:d});
}
}
if(!pairs.length)return null;
pairs.sort((x,y)=>x.diff-y.diff);
const pick=pairs[Math.floor(Math.random()*Math.min(12,pairs.length))];
const aId=pick.aId,bId=pick.bId;
const pA=setup.pit.winProb(aId,bId);
const house=0.10;
const fairA=1/pA,fairB=1/(1-pA);
const oddsA=setup.pit.clamp(fairA*(1-house),1.10,6.50);
const oddsB=setup.pit.clamp(fairB*(1-house),1.10,6.50);
const spectators=setup.pit.computeSpectators();
return{aId:aId,bId:bId,pA:pA,oddsA:oddsA,oddsB:oddsB,spectators:spectators,bettors:0,potA:0,potB:0,totalPot:0,houseCut:house,diff:pick.diff,isPlayerFight:false};
};
setup.pit.simulateCrowdBets=function(match){
const S=Math.max(0,+match.spectators||0);
const bettors=Math.floor(S*setup.pit.rnd(0.40,0.75));
match.bettors=bettors;
const pA=match.pA;
let potA=0,potB=0;
for(let i=0;i<bettors;i++){
const baseBet=setup.pit.rndInt(3,20);
const hype=setup.pit.clamp((S/300),0.6,2.2);
const bet=Math.max(5,Math.floor(baseBet*hype*setup.pit.rnd(0.85,1.20)));
const noise=setup.pit.rnd(-0.16,0.16);
const underdog=(pA>0.60)?setup.pit.rnd(0.06,0.14):(pA<0.40?setup.pit.rnd(-0.14,-0.06):0);
const perceived=setup.pit.clamp(pA+noise-underdog,0.08,0.92);
if(Math.random()<perceived)potA+=bet;else potB+=bet;
}
match.potA=potA;match.potB=potB;match.totalPot=potA+potB;
return match;
};
setup.pit.estimatePayout=function(match,pickId,stake){
stake=Math.max(0,Math.floor(+stake||0));
if(stake<=0)return 0;
const potA=match.potA+(pickId===match.aId?stake:0);
const potB=match.potB+(pickId===match.bId?stake:0);
const total=potA+potB;
const houseTake=Math.floor(total*match.houseCut);
const distributable=Math.max(0,total-houseTake);
const sidePot=(pickId===match.aId)?potA:potB;
if(sidePot<=0)return 0;
const ratio=distributable/sidePot;
return Math.floor(stake*ratio);
};
setup.pit.resolveMatch=function(match){const winA=(Math.random()<match.pA);return{winner:winA?match.aId:match.bId,winA:winA};};
setup.pit.applyElo=function(aId,bId,winnerId){
const V=State.variables;setup.pit.ensureLadder();
const A=V.PitLadder[aId],B=V.PitLadder[bId];if(!A||!B)return;
const ra=+A.elo||500,rb=+B.elo||500;
const Ea=1/(1+Math.pow(10,((rb-ra)/400)));
const Sa=(winnerId===aId)?1:0;
const Ka=24;
let newA=Math.round(ra+Ka*(Sa-Ea));
let newB=Math.round(rb+Ka*((1-Sa)-(1-Ea)));
if(newA<100)newA=100;if(newA>1000)newA=1000;
if(newB<100)newB=100;if(newB>1000)newB=1000;
A.elo=newA;B.elo=newB;
if(Sa===1){A.w=(+A.w||0)+1;B.l=(+B.l||0)+1;}
else{B.w=(+B.w||0)+1;A.l=(+A.l||0)+1;}
};
setup.pit.payoutPlayer=function(match,playerPickId,playerStake){
const stake=Math.max(0,Math.floor(+playerStake||0));
if(stake<=0)return{won:false,payout:0};
const payout=setup.pit.estimatePayout(match,playerPickId,stake);
return{won:true,payout:Math.max(0,payout)};
};
setup.pit.pickOpponentForPlayer=function(){
const V=State.variables;setup.pit.ensureLadder();
const pid=setup.pit.playerId;const pr=V.PitLadder[pid];if(!pr)return null;
const pE=+pr.elo||500;
const rows=setup.pit.getSorted().filter(r=>r.npc.id!==pid);
let pool=[];
for(let i=0;i<rows.length;i++){const e=+rows[i].rec.elo||500;if(Math.abs(e-pE)<=120)pool.push(rows[i].npc.id);}
if(!pool.length){
let best=null,bestD=1e9;
for(let i=0;i<rows.length;i++){const e=+rows[i].rec.elo||500,d=Math.abs(e-pE);if(d<bestD){bestD=d;best=rows[i].npc.id;}}
return best;
}
return pool[Math.floor(Math.random()*pool.length)];
};
setup.pit.makePlayerMatch=function(){
const V=State.variables;setup.pit.ensureLadder();
const foeId=setup.pit.pickOpponentForPlayer();if(!foeId)return null;
const pid=setup.pit.playerId;
const pA=setup.pit.winProb(pid,foeId);
const house=0.10;
const fairA=1/pA,fairB=1/(1-pA);
const oddsA=setup.pit.clamp(fairA*(1-house),1.10,6.50);
const oddsB=setup.pit.clamp(fairB*(1-house),1.10,6.50);
const diff=Math.abs((+V.PitLadder[pid].elo||500)-(+V.PitLadder[foeId].elo||500));
const spectators=setup.pit.computeSpectators();
return{aId:pid,bId:foeId,pA:pA,oddsA:oddsA,oddsB:oddsB,spectators:spectators,bettors:0,potA:0,potB:0,totalPot:0,houseCut:house,diff:diff,isPlayerFight:true};
};
setup.pit.fighterPurse=function(match,playerWon){
if(!match)return 0;
const total=Math.max(0,Math.floor(+match.totalPot||0));
const houseTake=Math.floor(total*(+match.houseCut||0.10));
const distributable=Math.max(0,total-houseTake);
const basePurse=Math.max(50,Math.floor(distributable*0.20));
if(!playerWon)return Math.floor(basePurse*0.10);
return basePurse;
};
setup.pit.preparePlayerPitFight=function(){
const V=State.variables;setup.pit.ensureLadder();setup.pit.ensureBetState();
let heal=Number(V.Heal);
if(!Number.isFinite(heal)||heal<20)return false;
const m=setup.pit.makePlayerMatch();if(!m)return false;
setup.pit.simulateCrowdBets(m);
V.PitBets.open=true;V.PitBets.match=m;V.PitBets.playerBet=null;V.PitBets.result=null;V.PitBets.lastPayout=0;
V.PitFight={pending:true,active:false,match:m,processed:false,purse:0};
V.PitCurrentOpponent=m.bId;
V.ReturnTo="ThePit";
return true;
};
setup.pit.startPreparedPitFight=function(){
const V=State.variables;
if(!V.PitFight||!V.PitFight.pending||!V.PitFight.match)return false;
setup.pit.ensureLadder();
const m=V.PitFight.match;
const foeId=m.bId;
const foeNpc=setup.pit.getNpcById(foeId);
const foeRec=V.PitLadder[foeId]||{elo:500};
const foeLvl=setup.pit.eloToLevel(+foeRec.elo||500);
const st=setup.pit.computeStats(foeNpc,foeLvl);
let hpNow=Number(V.Heal);
if(!Number.isFinite(hpNow)) hpNow=0;
hpNow=Math.floor(hpNow);
V.Fight={type:(foeNpc&&foeNpc.name)?String(foeNpc.name):"Enemy",lvl:st.fitness,playerMax:hpNow,enemyMax:st.hpMax,playerHP:hpNow,enemyHP:st.hpMax,playerBand:0,enemyBand:Math.floor(Math.random()*3)+1,playerStaMax:5,playerSta:5,healCD:0,log:[],p:{},e:{},enemyAtkMul:st.atkMul,enemyDodgeBias:st.dodgeBias};
V.PitFight.pending=false;
V.PitFight.active=true;
V.PitCurrentOpponent=foeId;
V.ReturnTo="ThePit";
return true;
};
setup.pit.beginPlayerPitFight=function(){
if(!setup.pit.preparePlayerPitFight())return false;
return setup.pit.startPreparedPitFight();
};
setup.pit.startPlayerPitFight=setup.pit.beginPlayerPitFight;
setup.pit.onFightEnd=function(playerWon){
const V=State.variables;setup.pit.ensureLadder();setup.pit.ensureBetState();
const pid=setup.pit.playerId;const foeId=V.PitCurrentOpponent;if(!foeId)return;
const m=(V.PitFight&&V.PitFight.match)?V.PitFight.match:null;
const before=V.PitLadder[pid]?+V.PitLadder[pid].elo||500:500;
const winner=playerWon?pid:foeId;
setup.pit.applyElo(pid,foeId,winner);
const after=V.PitLadder[pid]?+V.PitLadder[pid].elo||500:before;
const delta=after-before;
let purse=0,repGain=0;
if(playerWon&&m){
purse=setup.pit.fighterPurse(m,true);
V.Money=(+V.Money||0)+purse;
repGain=Math.max(1,Math.floor(delta*0.5));
V.Reputation=(+V.Reputation||0)+repGain;
V.PitBets.result={winner:pid,winA:true};
V.PitBets.lastPayout=purse;
}else{
purse=m?setup.pit.fighterPurse(m,false):0;
if(purse>0)V.Money=(+V.Money||0)+purse;
if(!Number.isFinite(+V.Heal)||+V.Heal<25)V.Heal=25;
V.PitBets.result={winner:foeId,winA:false};
V.PitBets.lastPayout=0;
}
V.PitLastPitResult={payout:purse,eloDelta:delta,newElo:after,repGain:repGain,won:!!playerWon};
if(V.PitFight){V.PitFight.processed=true;V.PitFight.purse=purse;}
V.PitCurrentOpponent=null;
};
setup.pit.finishPlayerPitFight=function(playerWon){
const V=State.variables;
setup.pit.ensureBetState();
if(V.PitFight&&V.PitFight.processed)return true;
setup.pit.onFightEnd(!!playerWon);
V.PitBets.open=false;
V.PitBets.match=null;
V.PitBets.playerBet=null;
if(V.PitFight){V.PitFight.pending=false;V.PitFight.active=false;}
return true;
};
<</script>>
--------------------------------------------------------------------------
<<widget "StoryStep">><<set _num = $args[0]>><<set _text = $args[1]>><<set _cur = $args[2]>><<set _fin = $args[3]>><<if _fin == false and _cur == false>>❌ <<print _num>> - <span class="legend-locked"><<print _text>></span><<elseif _cur == true>>➡️ <span class="legend-current"><<print _num>> - <<print _text>></span><<elseif _fin == true>>✅ <span class="legend-complete"><<print _num>> - <<print _text>></span><</if>><</widget>>
--------------------------------------------------------------------------
<<widget "OptionMenu">>
<<OpenHubMenu "OptionMenu">>
<</widget>>
--------------------------------------------------------------------------
<<widget "WIP">><style>
.wip-block{width:100%;min-height:60vh;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:20px;user-select:none;-webkit-user-select:none;pointer-events:none}
.wip-emoji{font-size:4rem;filter:grayscale(1) drop-shadow(0 2px 8px rgba(0,0,0,.5))}
.wip-title{font-size:1.9rem;font-weight:900;color:#c9d1e0;letter-spacing:.02em;text-align:center}
.wip-desc{font-size:1rem;color:#6b7a99;text-align:center;max-width:320px;line-height:1.6}
</style><div class="wip-block"><div class="wip-emoji">🚧</div><div class="wip-title">Work In Progress</div><div class="wip-desc">This page is not yet available.</div></div><</widget>>
--------------------------------------------------------------------------
/* <<FirstContact $NPC true/false>> */
<<widget "FirstContact">>
<<set _npc = $args[0]>><<set _askRole = ($args.length > 1 ? !!$args[1] : false)>><<if !_npc>><div class="fcError">FirstContact: NPC object missing.</div><<return>><</if>><<set _fcName = (typeof _npc.name === "string" ? _npc.name : "")>><<set _fcRole = (typeof _npc.role === "string" ? _npc.role : "")>><<set _interactNpc = _npc.id + ".interact">><style>
.fcBox{
margin: clamp(8px,1.5vw,14px) 0;
padding: clamp(10px,1.5vw,14px);
border-radius: 12px;
border: 1px solid rgba(230,87,99,.22);
background: rgba(255,255,255,.035);
box-shadow: 0 10px 22px rgba(0,0,0,.22);
backdrop-filter: blur(6px);
}
.fcTitle{
font-weight: 900;
font-size: calc(20px + var(--font-boost,0px));
letter-spacing: .3px;
margin-bottom: 6px;
}
.fcText{
font-size: calc(16px + var(--font-boost,0px));
opacity: .9;
margin-bottom: 12px;
line-height: 1.5;
}
.fcRow{
display: grid;
grid-template-columns: clamp(80px,15vw,120px) 1fr;
gap: clamp(6px,1vw,10px);
align-items: center;
margin: 8px 0;
}
.fcLabel{
font-weight: 800;
font-size: calc(16px + var(--font-boost,0px));
opacity: .9;
}
.fcRow input{
width: 100%;
box-sizing: border-box;
font-size: calc(16px + var(--font-boost,0px));
padding: clamp(4px,0.8vw,6px) clamp(6px,1vw,10px);
border-radius: 8px;
border: 1px solid rgba(255,255,255,.18);
background: rgba(255,255,255,.06);
color: rgba(255,255,255,.92);
font-family: inherit;
outline: none;
}
.fcRow input:focus{
border-color: rgba(230,87,99,.45);
background: rgba(255,255,255,.09);
}
.fcActions{
margin-top: clamp(8px,1.2vw,12px);
}
.fcBtn{
display: inline-block;
padding: clamp(6px,1vw,8px) clamp(10px,1.5vw,14px);
border-radius: 10px;
border: 1px solid rgba(230,87,99,.28);
background: rgba(255,255,255,.04);
font-weight: 900;
font-size: calc(16px + var(--font-boost,0px));
text-decoration: none;
cursor: pointer;
color: inherit;
font-family: inherit;
transition: border-color .15s, background .15s, opacity .15s;
}
.fcBtn:not(.fcDisabled):hover{
border-color: rgba(230,87,99,.6);
background: rgba(255,255,255,.06);
}
.fcBtn.fcDisabled{
opacity: .35;
cursor: not-allowed;
}
.fcError{
color: #e65763;
font-weight: 900;
font-size: calc(14px + var(--font-boost,0px));
}
</style><div class="fcBox"><div class="fcTitle">First encounter</div><div class="fcText">This is the first time you meet this person. You may choose how your character refers to them.</div><div class="fcRow"><div class="fcLabel">First name</div><<textbox "_fcName" _fcName>></div><<if _askRole>><div class="fcRow"><div class="fcLabel">Role</div><<textbox "_fcRole" _fcRole>></div><</if>><div class="fcActions"><button class="fcBtn fcDisabled" data-fc-confirm>Confirm</button></div></div><<script>>
(function(){
var askRole = State.temporary.askRole;
setTimeout(function(){
var box = document.querySelector(".fcBox");
if(!box) return;
var btn = box.querySelector("[data-fc-confirm]");
var inputs = box.querySelectorAll("input");
var ni = inputs[0] || null;
var ri = askRole ? (inputs[1] || null) : null;
if(ni) ni.setAttribute("maxlength","15");
if(ri) ri.setAttribute("maxlength","15");
function validate(){
var ok = ni && ni.value.length >= 1;
if(askRole && ri) ok = ok && ri.value.length >= 1;
btn.classList.toggle("fcDisabled", !ok);
}
btn.addEventListener("click", function(){
var nv = ni ? ni.value : "";
if(nv.length < 1) return;
if(askRole && ri && ri.value.length < 1) return;
var npc = State.temporary.npc;
npc.name = nv;
if(askRole && ri) npc.role = ri.value;
npc.met = true;
Engine.play(State.temporary.interactNpc);
});
if(ni) ni.addEventListener("input", validate);
if(ri) ri.addEventListener("input", validate);
validate();
}, 50);
})();
<</script>>
<</widget>>
-----------------------------------------------------------------------------
<<widget "PassageBackground" container>><<set _pbId = "pbSrc" + (setup._pbSeq = (setup._pbSeq || 0) + 1)>><style>
.pbSource{display:none!important}
.pbHasBg{position:relative}
.pbHasBg>.pbLayer{position:fixed;left:calc(var(--sc-ui-right,0px));right:0;top:var(--sc-topbar-h,0px);bottom:var(--sc-bottombar-h,0px);background-position:center;background-size:cover;background-repeat:no-repeat;opacity:.75;filter:blur(1px);transform:scale(1.01);pointer-events:none;z-index:999}
.pbHasBg>:not(.pbLayer){position:relative;z-index:1000}
.pbDbgBadge{position:fixed;left:calc(var(--sc-ui-right,0px) + 12px);bottom:calc(var(--sc-bottombar-h,0px) + 12px);z-index:999999;padding:6px 10px;border-radius:10px;font:700 12px/1 sans-serif;border:1px solid rgba(230,87,99,.45);background:rgba(8,8,8,.92);color:rgba(231,233,238,.98);pointer-events:none}
.pbDbgBad{border-color:rgba(231,76,60,.7)!important}
</style><span id="<<print _pbId>>" class="pbSource"><<print _contents>></span><<run (function(id){
function badge(msg,bad){
try{
var b=document.getElementById("pbDbgBadge");
if(!b){b=document.createElement("div");b.id="pbDbgBadge";b.className="pbDbgBadge";document.body.appendChild(b);}
b.textContent=msg;
if(bad) b.classList.add("pbDbgBad"); else b.classList.remove("pbDbgBad");
}catch(e){}
}
function findPassage(el){
if(!el) return null;
return el.closest(".passage") || el.closest("[data-passage]") || el.closest("#passages") || null;
}
function apply(){
try{
var srcWrap=document.getElementById(id);
if(!srcWrap){console.log("[PB] srcWrap not found",id);badge("PB: srcWrap not found",true);return false;}
var passage=findPassage(srcWrap);
if(!passage){console.log("[PB] passage not found for",id,srcWrap);badge("PB: passage not found",true);return false;}
var img=srcWrap.querySelector("img");
if(!img){console.log("[PB] img not found inside",id,srcWrap.innerHTML);badge("PB: img not found",true);return false;}
var src=img.getAttribute("src");
if(!src){console.log("[PB] img src empty",img);badge("PB: img src empty",true);return false;}
console.log("[PB] OK", {id:id, src:src, passage:passage});
passage.classList.add("pbHasBg");
var layer=passage.querySelector(".pbLayer");
if(!layer){
layer=document.createElement("div");
layer.className="pbLayer";
passage.insertBefore(layer, passage.firstChild);
}
layer.style.backgroundImage='url("' + String(src).replace(/"/g,'\\"') + '")';
badge("PB: " + src,false);
return true;
}catch(e){
console.log("[PB] exception",e);
badge("PB: exception (see console)",true);
return false;
}
}
setTimeout(function(){
if(apply()) return;
requestAnimationFrame(function(){
if(apply()) return;
setTimeout(apply,50);
});
},0);
})(_pbId)>><</widget>>
---------------------------------------------------------------------------
/* <<InformationUiPopUp "Title" "#color">> (Title and color optional) */
<<widget "InformationUiPopUp" container>><<set _t = $args[0]>><<set _c = $args[1]>><style>
.iupWrap{display:block;max-width:100%;box-sizing:border-box;padding:14px 16px;border-radius:14px;background:rgba(255,255,255,.04);backdrop-filter:blur(10px);border:1px solid rgba(255,255,255,.09);margin-bottom:10px;}
.iupTitle{font-weight:800;font-size:calc(11px + var(--font-boost,0px));text-transform:uppercase;letter-spacing:.15em;margin:0 0 10px 0;line-height:1;color:rgba(148,163,184,.8);display:flex;align-items:center;gap:6px;}
.iupTitle::before{content:'';display:inline-block;width:3px;height:.65rem;border-radius:2px;background:currentColor;opacity:.7;}
.iupBody{display:block;max-width:100%;box-sizing:border-box;color:#e2e8f0;font-size:calc(14px + var(--font-boost,0px));line-height:1.55;}
.iupWrap img{max-width:100%;height:auto;display:block;border-radius:8px;}
</style><<if _c>><<set _cc = String(_c)>><style>.iupWrap.iupTint{border-color:<<print _cc>>22} .iupWrap.iupTint .iupTitle{color:<<print _cc>>}</style><</if>><div class="iupWrap<<if _c>> iupTint<</if>>"><<if _t>><div class="iupTitle"><<print _t>></div><</if>><div class="iupBody"><<print _contents>></div></div><</widget>>
---------------------------------------------------------------------------
/* <<OpenHubMenu "OptionMenu">> */
/* <<HubLink "Options" "OptionMenu">> */
<<widget "OpenHubMenu">><<set _key=($args.length?String($args[0]):"")>><<run setup.openHubPass(_key)>><</widget>>
<<widget "HubLink">><<set _label=String($args[0]||"Open")>><<set _key=String($args[1]||"")>><<link _label>><<OpenHubMenu _key>><</link>><</widget>><<bgpause>><div id="supportcredits-root"></div><<script>>
(function(){
function esc(s){return String(s==null?"":s).replace(/[&<>"']/g,function(c){return({"&":"&","<":"<",">":">",'"':""","'":"'"}[c]);});}
var data = {
supportTitle: "SUPPORT & CREDITS",
supportSub: "Join the community, support development, and meet the team behind the scenes.",
support: {
title: "Support Development",
desc: "Your support directly funds new features, assets, and late night coding sessions. Join our community to get exclusive sneak peeks and influence the roadmap.",
links: [
{
key: "patreon",
title: "Become a Patron",
sub: "Get Exclusive Rewards",
href: "https://www.patreon.com/cw/EnthrallGame",
accent: "#eebba3",
logo: "assets/support/logopatreon.png",
span: 1
},
{
key: "subscribestar",
title: "SubscribeStar.adult",
sub: "Support Uncensored Content And Get Exclusive Rewards",
href: "https://subscribestar.adult/EnthrallGame",
accent: "#ff4081",
logo: "assets/support/logosubscribestar.png",
span: 1
},
{
key: "discord",
title: "Discord Community",
sub: "Join The Community And Help Shape The Development By Sharing Your Ideas!",
href: "https://discord.com/invite/jSTjBKSjvm",
accent: "#5865f2",
logo: "assets/support/logodiscord.png",
span: 2
}
]
},
credits: {
title: "CREDITS",
groups: [
{
title: "CORE TEAM",
items: [
{ name: "Enthrall", desc: "GAME CREATOR" },
]
},
{
title: "CHARACTER ACTORS",
items: [
{ name: "Kenzie Reeves", desc: State.variables.NPCHousemateFemale.name + " the " + State.variables.NPCHousemateFemale.role },
{ name: "Ava Addams", desc: State.variables.NPCLandlady.name + " the " + State.variables.NPCLandlady.role },
{ name: "Lucie Wilde", desc: State.variables.NPCBestFriend.name + " the " + State.variables.NPCBestFriend.role },
{ name: "Skylar Vox", desc: State.variables.NPCMate1.name + " the " + State.variables.NPCMate1.role },
{ name: "Crystal Chase", desc: State.variables.NPCMate2.name + " the " + State.variables.NPCMate2.role },
{ name: "Gabbie Carter", desc: State.variables.NPCMate3.name + " the " + State.variables.NPCMate3.role },
{ name: "Lauren Phillips", desc: State.variables.NPCPrincipal.name + " the " + State.variables.NPCPrincipal.role },
{ name: "Chanel Preston", desc: State.variables.NPCMayor.name + " the " + State.variables.NPCMayor.role },
{ name: "NyNyLew", desc: "NyLust the Stripper 1" },
{ name: "Ami Bue", desc: "Ima Blue the Stripper 2" },
{ name: "Valerica Steele", desc: "Valeela the Stripper 3" },
{ name: "Joanna Angel", desc: "Angel the Stripper 3" },
]
},
{
title: "MASTER SUBSCRIBER",
items: [
{ name: "How to become one?", desc: "HAVE A SUBSCRIPTION AT THE [MASTER] TIER." },
]
},
]
}
};
function arrowSvg(){
return '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><path fill="rgb(255,255,255)" d="M256 144C256 131.1 263.8 119.5 275.8 114.6C287.8 109.6 301.6 112.3 310.8 121.4L470.8 281.4C483.3 293.9 483.3 314.2 470.8 326.7L310.8 486.7C301.6 495.8 287.8 498.5 275.8 493.4C263.8 488.5 256 476.9 256 464L256 144z"/></svg>';
}
function render(){
var root=document.getElementById("supportcredits-root");
if(!root) return;
var linksHtml = (data.support.links||[]).map(function(x){
var span = (+x.span===2) ? ' scSpan2' : '';
return ''+
'<a class="scLinkCard'+span+'" href="'+esc(x.href)+'" target="_blank" rel="noopener noreferrer" style="--accent:'+esc(x.accent)+'" data-sckey="'+esc(x.key)+'" tabindex="0">'+
'<div class="scLogoWrap" aria-hidden="true">'+
'<img class="scLogo" src="'+esc(x.logo)+'" alt="">'+
'</div>'+
'<div class="scTxt">'+
'<div class="scTitle">'+esc(x.title)+'</div>'+
'<div class="scSub">'+esc(x.sub)+'</div>'+
'</div>'+
'<div class="scRight">'+
'<div class="scArrow" aria-hidden="true">'+arrowSvg()+'</div>'+
'</div>'+
'</a>';
}).join("");
var creditsGroupsHtml = (data.credits.groups||[]).map(function(g){
var items=(g.items||[]).map(function(it){
return ''+
'<div class="scCredItem">'+
'<div class="scCredName">'+esc(it.name)+'</div>'+
'<div class="scCredDesc">'+esc(it.desc||"")+'</div>'+
'</div>';
}).join("");
return ''+
'<div class="scCredGroup">'+
'<div class="scCredGroupTitle">'+esc(g.title)+'</div>'+
'<div class="scCredList">'+items+'</div>'+
'</div>';
}).join("");
root.innerHTML =
'<div class="scPage">'+
'<div class="scTop">'+
'<div class="scTopTitle">'+esc(data.supportTitle)+'</div>'+
'<div class="scTopSub">'+esc(data.supportSub)+'</div>'+
'</div>'+
'<div class="scSection">'+
'<div class="scCard">'+
'<div class="scCardHead">'+
'<div class="scCardTitle">'+esc(data.support.title)+'</div>'+
'<div class="scCardDesc">'+esc(data.support.desc)+'</div>'+
'</div>'+
'<div class="scGrid">'+linksHtml+'</div>'+
'</div>'+
'</div>'+
'<div class="scSection">'+
'<div class="scCard">'+
'<div class="scCreditsTitle">'+esc(data.credits.title)+'</div>'+
'<div class="scCreditsBody">'+
'<div class="scCreditsGrid">'+creditsGroupsHtml+'</div>'+
'</div>'+
'</div>'+
'</div>'+
'</div>';
}
function bind(){
var root=document.getElementById("supportcredits-root");
if(!root) return;
$(root).on("click.sc", ".scLinkCard", function(ev){
ev.preventDefault();
var url = $(this).attr("href");
if(!url) return;
try {
if(typeof nw !== "undefined" && nw.Shell) {
nw.Shell.openExternal(url);
} else {
window.open(url, "_blank", "noopener,noreferrer");
}
} catch(e) {
window.open(url, "_blank", "noopener,noreferrer");
}
});
}
function initWhenReady(tries){
var root=document.getElementById("supportcredits-root");
if(!root){
if(tries>0) requestAnimationFrame(function(){initWhenReady(tries-1);});
return;
}
if(root.dataset.scInit==="1") return;
root.dataset.scInit="1";
render();
bind();
}
initWhenReady(120);
})();<</script>><style>
#supportcredits-root{width:100%;height:100%;}
#supportcredits-root *{box-sizing:border-box;}
.scPage{width:100%;min-height:100%;padding:clamp(18px,3vw,32px) clamp(18px,3vw,34px) clamp(18px,3vw,34px) clamp(18px,3vw,34px);}
.scTop{padding:8px 0 18px 0;}
.scTopTitle{font-size:clamp(22px,3vw,34px);font-weight:950;letter-spacing:.06em;text-transform:uppercase;color:rgba(255,255,255,.95);line-height:1.05;}
.scTopSub{margin-top:10px;color:rgba(255,255,255,.45);font-size:calc(14px + var(--font-boost,0px));line-height:1.55;max-width:860px;}
.scSection{margin-top:22px;}
.scCard{border-radius:14px;border:1px solid rgba(255,255,255,.10);background:rgba(255,255,255,.03);overflow:hidden;}
.scCardHead{padding:clamp(14px,2vw,22px);}
.scCardTitle{font-size:calc(18px + var(--font-boost,0px));font-weight:950;color:rgba(255,255,255,.92);}
.scCardDesc{margin-top:10px;font-size:calc(14px + var(--font-boost,0px));line-height:1.6;color:rgba(255,255,255,.42);max-width:980px;}
.scGrid{padding:16px clamp(14px,2vw,22px) 22px clamp(14px,2vw,22px);display:grid;grid-template-columns:1fr 1fr;gap:14px;}
.scSpan2{grid-column:1 / span 2;}
@media (max-width:980px){.scPage{padding:22px 18px 26px 18px;}.scGrid{grid-template-columns:1fr;}.scSpan2{grid-column:auto;}}
.scLinkCard{position:relative;display:flex;align-items:center;gap:clamp(10px,2vw,18px);padding:clamp(12px,2vw,18px);border-radius:12px;border:1px solid rgba(255,255,255,.10);background:rgba(0,0,0,.22);text-decoration:none;user-select:none;cursor:pointer;outline:none;min-height:74px;transition:transform .12s ease, border-color .12s ease, background .12s ease;}
.scLinkCard:focus-visible{outline:3px solid rgba(255,255,255,.25);outline-offset:3px;}
.scLinkCard:hover{transform:translateY(-1px);border-color:color-mix(in srgb, var(--accent) 55%, rgba(255,255,255,.18));background:color-mix(in srgb, rgba(255,255,255,.06) 68%, var(--accent));}
.scTxt{min-width:0;flex:1 1 auto;}
.scTitle{font-size:calc(14px + var(--font-boost,0px));font-weight:950;letter-spacing:.02em;color:rgba(255,255,255,.90);}
.scSub{margin-top:4px;font-size:calc(14px + var(--font-boost,0px));color:rgba(255,255,255,.50);}
.scRight{display:flex;align-items:center;gap:12px;flex:0 0 auto;}
.scLogoWrap{width:34px;height:34px;border-radius:999px;border:1px solid rgba(255,255,255,.12);background:rgba(255,255,255,.04);display:flex;align-items:center;justify-content:center;overflow:hidden;flex:0 0 auto;}
.scLogo{max-width:34px !important;min-width:34px !important;max-height:34px !important;min-height:34px !important;object-fit:contain !important;display:block !important;pointer-events:none !important;opacity:.95 !important;}
.scArrow{width:22px;height:22px;display:flex;align-items:center;justify-content:center;opacity:0;transform:translateX(-6px);transition:opacity .12s ease, transform .12s ease;flex:0 0 auto;}
.scArrow svg{width:18px;height:18px;opacity:.9;}
.scLinkCard:hover .scArrow{opacity:1;transform:translateX(0);}
.scCreditsTitle{padding:clamp(14px,2vw,22px) clamp(14px,2vw,22px) 16px clamp(14px,2vw,22px);font-size:calc(14px + var(--font-boost,0px));font-weight:950;letter-spacing:.22em;text-transform:uppercase;color:rgba(255,255,255,.92);}
.scCreditsBody{padding:0 clamp(14px,2vw,22px) 26px clamp(14px,2vw,22px);}
.scCreditsGrid{display:grid;grid-template-columns:repeat(4, minmax(180px, 1fr));gap:18px 22px;align-items:start;}
@media (max-width:1200px){.scCreditsGrid{grid-template-columns:repeat(3, minmax(180px, 1fr));}}
@media (max-width:980px){.scCreditsGrid{grid-template-columns:repeat(2, minmax(180px, 1fr));}}
@media (max-width:640px){.scCreditsGrid{grid-template-columns:1fr;}}
.scCredGroup{padding:clamp(12px,2vw,18px) clamp(12px,2vw,16px);border-radius:12px;border:1px solid rgba(255,255,255,.08);background:rgba(0,0,0,.22);min-height:220px;}
.scCredGroupTitle{font-size:calc(14px + var(--font-boost,0px));font-weight:950;letter-spacing:.22em;text-transform:uppercase;color:rgba(230,87,99,.95);margin:0 0 14px 0;}
.scCredList{display:flex;flex-direction:column;gap:20px;}
.scCredItem{min-width:0;}
.scCredName{font-size:calc(14px + var(--font-boost,0px));font-weight:600;color:rgba(255,255,255,.92);}
.scCredDesc{margin-top:5px;font-size:calc(14px + var(--font-boost,0px));font-weight:400;letter-spacing:.18em;text-transform:uppercase;color:rgba(255,255,255,.40);line-height:1.4;}
</style><<sound "music" "music.music" true>><<sound "bg" "bg.store" true>><<if $Time == 3>><<goto "Mall">><</if>><<passagebg>><img src="assets/img/misc/city/mall/clothingstore.webp"/><</passagebg>><<if $Time == 1 or 2>><<Interact $NPCLeftNeighbor>><<else>><<InformationUiPopUp "Interact">>There is no one.<</InformationUiPopUp>><</if>>
<<set _shopVar = "ShopClothing">><<set _shop to State.variables[_shopVar]>><style>
.shp-wrap{display:flex;flex-direction:column;gap:14px;padding:4px 2px;}
.shp-topbar{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;padding:clamp(8px,2vw,12px) clamp(10px,2vw,16px);border-radius:14px;background:rgba(0,0,0,.45);border:1px solid rgba(255,255,255,.10);}
.shp-topbar-title{font-size:calc(24px + var(--font-boost,0px));font-weight:950;color:rgba(255,255,255,.96);letter-spacing:-.01em;}
.shp-topbar-notice{font-size:calc(14px + var(--font-boost,0px));font-weight:800;color:rgba(230,87,99,.85);letter-spacing:.06em;text-transform:uppercase;margin-top:3px;}
.shp-balances{display:flex;gap:10px;flex-wrap:wrap;}
.shp-bal{display:flex;flex-direction:column;align-items:flex-end;gap:2px;padding:8px 14px;border-radius:10px;background:rgba(0,0,0,.45);border:1px solid rgba(255,255,255,.10);}
.shp-bal-label{font-size:calc(14px + var(--font-boost,0px));font-weight:900;letter-spacing:.12em;text-transform:uppercase;color:rgba(255,255,255,.65);}
.shp-bal-value{font-size:calc(16px + var(--font-boost,0px));font-weight:950;color:rgba(255,255,255,.96);letter-spacing:-.01em;}
.shp-grid{display:grid;grid-template-columns:repeat(auto-fill, minmax(clamp(140px,15vw,170px), 1fr));gap:10px;}
.shp-card{display:flex;flex-direction:column;border-radius:14px;background:rgba(0,0,0,.45);border:1px solid rgba(255,255,255,.10);overflow:hidden;transition:border-color .14s, background .14s, transform .14s;}
.shp-card:hover{border-color:rgba(255,255,255,.20);background:rgba(0,0,0,.35);transform:translateY(-2px);}
.shp-card-img-wrap{width:100%;aspect-ratio:1;background:#f0f0f0;display:flex;align-items:center;justify-content:center;line-height:0;font-size:0;}
.shp-card-img-wrap img{width:100%!important;height:100%!important;min-width:unset!important;max-width:unset!important;min-height:unset!important;max-height:unset!important;object-fit:contain!important;display:block!important;margin:0!important;}
.shp-card-body{display:flex;flex-direction:column;gap:6px;padding:clamp(8px,2vw,10px) clamp(8px,2vw,10px) clamp(10px,2vw,12px);flex:1 1 auto;}
.shp-card-name{font-size:calc(15px + var(--font-boost,0px));font-weight:950;color:rgba(255,255,255,.96);letter-spacing:.01em;line-height:1.2;}
.shp-card-desc{font-size:calc(14px + var(--font-boost,0px));color:rgba(255,255,255,.75);font-weight:600;line-height:1.35;flex:1 1 auto;}
.shp-card-price{font-size:calc(16px + var(--font-boost,0px));font-weight:950;color:#e65763;letter-spacing:-.01em;}
.shp-card-actions{display:grid;grid-template-columns:1fr 1fr;gap:6px;margin-top:2px;}
.shp-btn{padding:8px 0;border-radius:9px;border:1px solid rgba(230,87,99,.40);background:rgba(230,87,99,.14);color:rgba(230,87,99,.98);font-weight:950;font-size:calc(14px + var(--font-boost,0px));letter-spacing:.08em;text-align:center;cursor:pointer;user-select:none;transition:background .12s, border-color .12s;text-decoration:none!important;display:block;}
.shp-btn:hover{background:rgba(230,87,99,.24);border-color:rgba(230,87,99,.60);}
.shp-btn-disabled{opacity:.45;pointer-events:none;display:block;width:100%;padding:8px 0;border-radius:9px;border:1px solid rgba(255,255,255,.15);background:rgba(0,0,0,.40);color:rgba(255,255,255,.60);font-weight:950;font-size:calc(14px + var(--font-boost,0px));letter-spacing:.08em;text-align:center;box-sizing:border-box;}
</style><div class="shp-wrap"><div class="shp-topbar"><div><div class="shp-topbar-title">Clothing Store</div><div class="shp-topbar-notice">⚠ Purchases grant reputation</div></div><div class="shp-balances"><div class="shp-bal"><div class="shp-bal-label">Money</div><div class="shp-bal-value">$<<=$Money>></div></div><div class="shp-bal"><div class="shp-bal-label">Bank</div><div class="shp-bal-value">$<<=$Bank>></div></div></div></div><div class="shp-grid"><<for _i = 0; _i < _shop.length; _i++>><<set _p = _shop[_i]>><<if !(_p.unique && _p.bought)>><div class="shp-card"><div class="shp-card-img-wrap"><<if _p.img and _p.img !== "">><<= '<img src="'+_p.img+'" alt="'+_p.name+'">'>><<else>><span style="font-size:14px;opacity:.5;color:#000;">No image</span><</if>></div><div class="shp-card-body"><div class="shp-card-name"><<= _p.name>></div><div class="shp-card-desc"><<if _p.desc == "">>—<<else>><<= _p.desc>><</if>></div><div class="shp-card-price">$<<= +_p.price>></div><<capture _i _p>><div class="shp-card-actions"><<if $Money >= +_p.price>><div><<link "<div class='shp-btn'>MONEY</div>">><<if $Money >= +_p.price>><<set $Money -= +_p.price>><<if _p.inventory>><<set $Inventory[_p.id] to $Inventory[_p.id] or {id:_p.id, name:_p.name, img:_p.img or "", qty:0, desc:_p.desc or ""}>><<if !$Inventory[_p.id].desc and _p.desc>><<set $Inventory[_p.id].desc = _p.desc>><</if>><<set $Inventory[_p.id].qty += 1>><</if>><<set _p.bought = true>><<Refresh>><</if>><</link>></div><<else>><div class="shp-btn-disabled">MONEY</div><</if>><<if $Bank >= +_p.price>><div><<link "<div class='shp-btn'>BANK</div>">><<if $Bank >= +_p.price>><<set $Bank -= +_p.price>><<if _p.inventory>><<set $Inventory[_p.id] to $Inventory[_p.id] or {id:_p.id, name:_p.name, img:_p.img or "", qty:0, desc:_p.desc or ""}>><<if !$Inventory[_p.id].desc and _p.desc>><<set $Inventory[_p.id].desc = _p.desc>><</if>><<set $Inventory[_p.id].qty += 1>><</if>><<set _p.bought = true>><<Refresh>><</if>><</link>></div><<else>><div class="shp-btn-disabled">BANK</div><</if>></div><</capture>></div></div><</if>><</for>></div></div>
<div class="BottomUiBarCustom">
<<BottomButton "Move">>[[🛍️ Mall|Mall]]<</BottomButton>>
</div><<sound "music" "music.music" true>><<sound "bg" "bg.store" true>><<if $Time == 3>><<goto "Mall">><</if>><<passagebg>><img src="assets/img/misc/city/mall/electronicstore.webp"/><</passagebg>>
<<set _shopVar = "ShopElectronic">><<set _shop to State.variables[_shopVar]>><style>
.shp-wrap{display:flex;flex-direction:column;gap:14px;padding:4px 2px;}
.shp-topbar{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;padding:clamp(8px,2vw,12px) clamp(10px,2vw,16px);border-radius:14px;background:rgba(0,0,0,.45);border:1px solid rgba(255,255,255,.10);}
.shp-topbar-title{font-size:calc(24px + var(--font-boost,0px));font-weight:950;color:rgba(255,255,255,.96);letter-spacing:-.01em;}
.shp-balances{display:flex;gap:10px;flex-wrap:wrap;}
.shp-bal{display:flex;flex-direction:column;align-items:flex-end;gap:2px;padding:8px 14px;border-radius:10px;background:rgba(0,0,0,.45);border:1px solid rgba(255,255,255,.10);}
.shp-bal-label{font-size:calc(14px + var(--font-boost,0px));font-weight:900;letter-spacing:.12em;text-transform:uppercase;color:rgba(255,255,255,.65);}
.shp-bal-value{font-size:calc(16px + var(--font-boost,0px));font-weight:950;color:rgba(255,255,255,.96);letter-spacing:-.01em;}
.shp-grid{display:grid;grid-template-columns:repeat(auto-fill, minmax(clamp(140px,15vw,170px), 1fr));gap:10px;}
.shp-card{display:flex;flex-direction:column;border-radius:14px;background:rgba(0,0,0,.45);border:1px solid rgba(255,255,255,.10);overflow:hidden;transition:border-color .14s, background .14s, transform .14s;}
.shp-card:hover{border-color:rgba(255,255,255,.20);background:rgba(0,0,0,.35);transform:translateY(-2px);}
.shp-card-img-wrap{width:100%;aspect-ratio:1;background:#f0f0f0;display:flex;align-items:center;justify-content:center;line-height:0;font-size:0;}
.shp-card-img-wrap img{width:100%!important;height:100%!important;min-width:unset!important;max-width:unset!important;min-height:unset!important;max-height:unset!important;object-fit:contain!important;display:block!important;margin:0!important;}
.shp-card-body{display:flex;flex-direction:column;gap:6px;padding:clamp(8px,2vw,10px) clamp(8px,2vw,10px) clamp(10px,2vw,12px);flex:1 1 auto;}
.shp-card-name{font-size:calc(15px + var(--font-boost,0px));font-weight:950;color:rgba(255,255,255,.96);letter-spacing:.01em;line-height:1.2;}
.shp-card-desc{font-size:calc(14px + var(--font-boost,0px));color:rgba(255,255,255,.75);font-weight:600;line-height:1.35;flex:1 1 auto;}
.shp-card-price{font-size:calc(16px + var(--font-boost,0px));font-weight:950;color:#e65763;letter-spacing:-.01em;}
.shp-card-actions{display:grid;grid-template-columns:1fr 1fr;gap:6px;margin-top:2px;}
.shp-btn{padding:8px 0;border-radius:9px;border:1px solid rgba(230,87,99,.40);background:rgba(230,87,99,.14);color:rgba(230,87,99,.98);font-weight:950;font-size:calc(14px + var(--font-boost,0px));letter-spacing:.08em;text-align:center;cursor:pointer;user-select:none;transition:background .12s, border-color .12s;text-decoration:none!important;display:block;}
.shp-btn:hover{background:rgba(230,87,99,.24);border-color:rgba(230,87,99,.60);}
.shp-btn-disabled{opacity:.45;pointer-events:none;display:block;width:100%;padding:8px 0;border-radius:9px;border:1px solid rgba(255,255,255,.15);background:rgba(0,0,0,.40);color:rgba(255,255,255,.60);font-weight:950;font-size:calc(14px + var(--font-boost,0px));letter-spacing:.08em;text-align:center;box-sizing:border-box;}
</style><div class="shp-wrap"><div class="shp-topbar"><div><div class="shp-topbar-title">Electronic Store</div></div><div class="shp-balances"><div class="shp-bal"><div class="shp-bal-label">Money</div><div class="shp-bal-value">$<<=$Money>></div></div><div class="shp-bal"><div class="shp-bal-label">Bank</div><div class="shp-bal-value">$<<=$Bank>></div></div></div></div><div class="shp-grid"><<for _i = 0; _i < _shop.length; _i++>><<set _p = _shop[_i]>><<if !(_p.unique && _p.bought)>><div class="shp-card"><div class="shp-card-img-wrap"><<if _p.img and _p.img !== "">><<= '<img src="'+_p.img+'" alt="'+_p.name+'">'>><<else>><span style="font-size:14px;opacity:.5;color:#000;">No image</span><</if>></div><div class="shp-card-body"><div class="shp-card-name"><<= _p.name>></div><div class="shp-card-desc"><<if _p.desc == "">>—<<else>><<= _p.desc>><</if>></div><div class="shp-card-price">$<<= +_p.price>></div><<capture _i _p>><div class="shp-card-actions"><<if $Money >= +_p.price>><div><<link "<div class='shp-btn'>MONEY</div>">><<if $Money >= +_p.price>><<set $Money -= +_p.price>><<if _p.inventory>><<set $Inventory[_p.id] to $Inventory[_p.id] or {id:_p.id, name:_p.name, img:_p.img or "", qty:0, desc:_p.desc or ""}>><<if !$Inventory[_p.id].desc and _p.desc>><<set $Inventory[_p.id].desc = _p.desc>><</if>><<set $Inventory[_p.id].qty += 1>><</if>><<set _p.bought = true>><<Refresh>><</if>><</link>></div><<else>><div class="shp-btn-disabled">MONEY</div><</if>><<if $Bank >= +_p.price>><div><<link "<div class='shp-btn'>BANK</div>">><<if $Bank >= +_p.price>><<set $Bank -= +_p.price>><<if _p.inventory>><<set $Inventory[_p.id] to $Inventory[_p.id] or {id:_p.id, name:_p.name, img:_p.img or "", qty:0, desc:_p.desc or ""}>><<if !$Inventory[_p.id].desc and _p.desc>><<set $Inventory[_p.id].desc = _p.desc>><</if>><<set $Inventory[_p.id].qty += 1>><</if>><<set _p.bought = true>><<Refresh>><</if>><</link>></div><<else>><div class="shp-btn-disabled">BANK</div><</if>></div><</capture>></div></div><</if>><</for>></div></div>
<div class="BottomUiBarCustom">
<<BottomButton "Move">>[[🛍️ Mall|Mall]]<</BottomButton>>
</div><<sound "music" "music.music" true>><<sound "bg" "bg.store" true>><<if $Time == 3>><<goto "Mall">><</if>><<passagebg>><img src="assets/img/misc/city/mall/supermarket.webp"/><</passagebg>>
<<if $Time !== 3>><<Interact $NPCBossMarket>><<else>><<InformationUiPopUp "Interact">>There is no one.<</InformationUiPopUp>><</if>>
<<set _shopVar = "ShopMarket">><<set _shop to State.variables[_shopVar]>><style>
.shp-wrap{display:flex;flex-direction:column;gap:14px;padding:4px 2px;}
.shp-topbar{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;padding:clamp(8px,2vw,12px) clamp(10px,2vw,16px);border-radius:14px;background:rgba(0,0,0,.45);border:1px solid rgba(255,255,255,.10);}
.shp-topbar-title{font-size:calc(24px + var(--font-boost,0px));font-weight:950;color:rgba(255,255,255,.96);letter-spacing:-.01em;}
.shp-balances{display:flex;gap:10px;flex-wrap:wrap;}
.shp-bal{display:flex;flex-direction:column;align-items:flex-end;gap:2px;padding:8px 14px;border-radius:10px;background:rgba(0,0,0,.45);border:1px solid rgba(255,255,255,.10);}
.shp-bal-label{font-size:calc(14px + var(--font-boost,0px));font-weight:900;letter-spacing:.12em;text-transform:uppercase;color:rgba(255,255,255,.65);}
.shp-bal-value{font-size:calc(16px + var(--font-boost,0px));font-weight:950;color:rgba(255,255,255,.96);letter-spacing:-.01em;}
.shp-grid{display:grid;grid-template-columns:repeat(auto-fill, minmax(clamp(140px,15vw,170px), 1fr));gap:10px;}
.shp-card{display:flex;flex-direction:column;border-radius:14px;background:rgba(0,0,0,.45);border:1px solid rgba(255,255,255,.10);overflow:hidden;transition:border-color .14s, background .14s, transform .14s;}
.shp-card:hover{border-color:rgba(255,255,255,.20);background:rgba(0,0,0,.35);transform:translateY(-2px);}
.shp-card-img-wrap{width:100%;aspect-ratio:1;background:#f0f0f0;display:flex;align-items:center;justify-content:center;line-height:0;font-size:0;}
.shp-card-img-wrap img{width:100%!important;height:100%!important;min-width:unset!important;max-width:unset!important;min-height:unset!important;max-height:unset!important;object-fit:contain!important;display:block!important;margin:0!important;}
.shp-card-body{display:flex;flex-direction:column;gap:6px;padding:clamp(8px,2vw,10px) clamp(8px,2vw,10px) clamp(10px,2vw,12px);flex:1 1 auto;}
.shp-card-name{font-size:calc(15px + var(--font-boost,0px));font-weight:950;color:rgba(255,255,255,.96);letter-spacing:.01em;line-height:1.2;}
.shp-card-desc{font-size:calc(14px + var(--font-boost,0px));color:rgba(255,255,255,.75);font-weight:600;line-height:1.35;flex:1 1 auto;}
.shp-card-price{font-size:calc(16px + var(--font-boost,0px));font-weight:950;color:#e65763;letter-spacing:-.01em;}
.shp-card-actions{display:grid;grid-template-columns:1fr 1fr;gap:6px;margin-top:2px;}
.shp-btn{padding:8px 0;border-radius:9px;border:1px solid rgba(230,87,99,.40);background:rgba(230,87,99,.14);color:rgba(230,87,99,.98);font-weight:950;font-size:calc(14px + var(--font-boost,0px));letter-spacing:.08em;text-align:center;cursor:pointer;user-select:none;transition:background .12s, border-color .12s;text-decoration:none!important;display:block;}
.shp-btn:hover{background:rgba(230,87,99,.24);border-color:rgba(230,87,99,.60);}
.shp-btn-disabled{opacity:.45;pointer-events:none;display:block;width:100%;padding:8px 0;border-radius:9px;border:1px solid rgba(255,255,255,.15);background:rgba(0,0,0,.40);color:rgba(255,255,255,.60);font-weight:950;font-size:calc(14px + var(--font-boost,0px));letter-spacing:.08em;text-align:center;box-sizing:border-box;}
</style><div class="shp-wrap"><div class="shp-topbar"><div><div class="shp-topbar-title">Supermarket</div></div><div class="shp-balances"><div class="shp-bal"><div class="shp-bal-label">Money</div><div class="shp-bal-value">$<<=$Money>></div></div><div class="shp-bal"><div class="shp-bal-label">Bank</div><div class="shp-bal-value">$<<=$Bank>></div></div></div></div><div class="shp-grid"><<for _i = 0; _i < _shop.length; _i++>><<set _p = _shop[_i]>><<if !(_p.unique && _p.bought)>><div class="shp-card"><div class="shp-card-img-wrap"><<if _p.img and _p.img !== "">><<= '<img src="'+_p.img+'" alt="'+_p.name+'">'>><<else>><span style="font-size:14px;opacity:.5;color:#000;">No image</span><</if>></div><div class="shp-card-body"><div class="shp-card-name"><<= _p.name>></div><div class="shp-card-desc"><<if _p.desc == "">>—<<else>><<= _p.desc>><</if>></div><div class="shp-card-price">$<<= +_p.price>></div><<capture _i _p>><div class="shp-card-actions"><<if $Money >= +_p.price>><div><<link "<div class='shp-btn'>MONEY</div>">><<if $Money >= +_p.price>><<set $Money -= +_p.price>><<if _p.inventory>><<set $Inventory[_p.id] to $Inventory[_p.id] or {id:_p.id, name:_p.name, img:_p.img or "", qty:0, desc:_p.desc or ""}>><<if !$Inventory[_p.id].desc and _p.desc>><<set $Inventory[_p.id].desc = _p.desc>><</if>><<set $Inventory[_p.id].qty += 1>><</if>><<set _p.bought = true>><<Refresh>><</if>><</link>></div><<else>><div class="shp-btn-disabled">MONEY</div><</if>><<if $Bank >= +_p.price>><div><<link "<div class='shp-btn'>BANK</div>">><<if $Bank >= +_p.price>><<set $Bank -= +_p.price>><<if _p.inventory>><<set $Inventory[_p.id] to $Inventory[_p.id] or {id:_p.id, name:_p.name, img:_p.img or "", qty:0, desc:_p.desc or ""}>><<if !$Inventory[_p.id].desc and _p.desc>><<set $Inventory[_p.id].desc = _p.desc>><</if>><<set $Inventory[_p.id].qty += 1>><</if>><<set _p.bought = true>><<Refresh>><</if>><</link>></div><<else>><div class="shp-btn-disabled">BANK</div><</if>></div><</capture>></div></div><</if>><</for>></div></div>
<div class="BottomUiBarCustom">
<<BottomButton "Move">>[[🛍️ Mall|Mall]]<</BottomButton>>
</div><<sound "music" "music.music" true>><<sound "bg" "bg.mall" true>><<if $Time == 3>><<goto "Mall">><</if>><<passagebg>><img src="assets/img/misc/city/mall/gym/gym.webp"/><</passagebg>><<if $Time !== 3>><<Interact $NPCBossGym>><<else>><<InformationUiPopUp "Interact">>There is no one.<</InformationUiPopUp>><</if>>
<<imgcorruption gym>>
<div class="BottomUiBarCustom">
<<BottomButton "Action">><<if $GymSub == false>>[[💬 View reception|SubToGym]]<<elseif $FitnessDayTime == false>>[[🏋️ Workout session|GymWorkout]]<<set _GymDaysLeft = Math.max(0, 10 - ($Day - $GymSubDayInt))>> <em>| You have: <<=_GymDaysLeft>> subscription day(s) left</em><<elseif $FitnessDayTime == true>><<link "😩 Already Exercised Today">><</link>><</if>><</BottomButton>>
<<BottomButton "Move">>[[🛍️ Mall|Mall]]<</BottomButton>>
</div><<sound "music" "music.music" true>><<sound "bg" "bg.mall" true>><<if $Time == 3>><<goto "Mall">><</if>><<passagebg>><img src="assets/img/misc/city/mall/cardealer.webp"/><</passagebg>>
<<set _shopVar = "ShopCar">><<set _shop to State.variables[_shopVar]>><style>
.shp-wrap{display:flex;flex-direction:column;gap:14px;padding:4px 2px;}
.shp-topbar{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;padding:clamp(8px,2vw,12px) clamp(10px,2vw,16px);border-radius:14px;background:rgba(0,0,0,.45);border:1px solid rgba(255,255,255,.10);}
.shp-topbar-title{font-size:calc(24px + var(--font-boost,0px));font-weight:950;color:rgba(255,255,255,.96);letter-spacing:-.01em;}
.shp-topbar-notice{font-size:calc(14px + var(--font-boost,0px));font-weight:800;color:rgba(230,87,99,.85);letter-spacing:.06em;text-transform:uppercase;margin-top:3px;}
.shp-balances{display:flex;gap:10px;flex-wrap:wrap;}
.shp-bal{display:flex;flex-direction:column;align-items:flex-end;gap:2px;padding:8px 14px;border-radius:10px;background:rgba(0,0,0,.45);border:1px solid rgba(255,255,255,.10);}
.shp-bal-label{font-size:calc(14px + var(--font-boost,0px));font-weight:900;letter-spacing:.12em;text-transform:uppercase;color:rgba(255,255,255,.65);}
.shp-bal-value{font-size:calc(16px + var(--font-boost,0px));font-weight:950;color:rgba(255,255,255,.96);letter-spacing:-.01em;}
.shp-grid{display:grid;grid-template-columns:repeat(auto-fill, minmax(clamp(140px,15vw,170px), 1fr));gap:10px;}
.shp-card{display:flex;flex-direction:column;border-radius:14px;background:rgba(0,0,0,.45);border:1px solid rgba(255,255,255,.10);overflow:hidden;transition:border-color .14s, background .14s, transform .14s;}
.shp-card:hover{border-color:rgba(255,255,255,.20);background:rgba(0,0,0,.35);transform:translateY(-2px);}
.shp-card-img-wrap{width:100%;aspect-ratio:1;background:#f0f0f0;display:flex;align-items:center;justify-content:center;line-height:0;font-size:0;}
.shp-card-img-wrap img{width:100%!important;height:100%!important;min-width:unset!important;max-width:unset!important;min-height:unset!important;max-height:unset!important;object-fit:contain!important;display:block!important;margin:0!important;}
.shp-card-body{display:flex;flex-direction:column;gap:6px;padding:clamp(8px,2vw,10px) clamp(8px,2vw,10px) clamp(10px,2vw,12px);flex:1 1 auto;}
.shp-card-name{font-size:calc(15px + var(--font-boost,0px));font-weight:950;color:rgba(255,255,255,.96);letter-spacing:.01em;line-height:1.2;}
.shp-card-desc{font-size:calc(14px + var(--font-boost,0px));color:rgba(255,255,255,.75);font-weight:600;line-height:1.35;flex:1 1 auto;}
.shp-card-price{font-size:calc(16px + var(--font-boost,0px));font-weight:950;color:#e65763;letter-spacing:-.01em;}
.shp-card-actions{display:grid;grid-template-columns:1fr 1fr;gap:6px;margin-top:2px;}
.shp-btn{padding:8px 0;border-radius:9px;border:1px solid rgba(230,87,99,.40);background:rgba(230,87,99,.14);color:rgba(230,87,99,.98);font-weight:950;font-size:calc(14px + var(--font-boost,0px));letter-spacing:.08em;text-align:center;cursor:pointer;user-select:none;transition:background .12s, border-color .12s;text-decoration:none!important;display:block;}
.shp-btn:hover{background:rgba(230,87,99,.24);border-color:rgba(230,87,99,.60);}
.shp-btn-disabled{opacity:.45;pointer-events:none;display:block;width:100%;padding:8px 0;border-radius:9px;border:1px solid rgba(255,255,255,.15);background:rgba(0,0,0,.40);color:rgba(255,255,255,.60);font-weight:950;font-size:calc(14px + var(--font-boost,0px));letter-spacing:.08em;text-align:center;box-sizing:border-box;}
</style><div class="shp-wrap"><div class="shp-topbar"><div><div class="shp-topbar-title">Car Dealer</div><div class="shp-topbar-notice">⚠ Purchases grant reputation</div></div><div class="shp-balances"><div class="shp-bal"><div class="shp-bal-label">Money</div><div class="shp-bal-value">$<<=$Money>></div></div><div class="shp-bal"><div class="shp-bal-label">Bank</div><div class="shp-bal-value">$<<=$Bank>></div></div></div></div><div class="shp-grid"><<for _i = 0; _i < _shop.length; _i++>><<set _p = _shop[_i]>><<if !(_p.unique && _p.bought)>><div class="shp-card"><div class="shp-card-img-wrap"><<if _p.img and _p.img !== "">><<= '<img src="'+_p.img+'" alt="'+_p.name+'">'>><<else>><span style="font-size:14px;opacity:.5;color:#000;">No image</span><</if>></div><div class="shp-card-body"><div class="shp-card-name"><<= _p.name>></div><div class="shp-card-desc"><<if _p.desc == "">>—<<else>><<= _p.desc>><</if>></div><div class="shp-card-price">$<<= +_p.price>></div><<capture _i _p>><div class="shp-card-actions"><<if $Money >= +_p.price>><div><<link "<div class='shp-btn'>MONEY</div>">><<if $Money >= +_p.price>><<set $Money -= +_p.price>><<if _p.inventory>><<set $Inventory[_p.id] to $Inventory[_p.id] or {id:_p.id, name:_p.name, img:_p.img or "", qty:0, desc:_p.desc or ""}>><<if !$Inventory[_p.id].desc and _p.desc>><<set $Inventory[_p.id].desc = _p.desc>><</if>><<set $Inventory[_p.id].qty += 1>><</if>><<set _p.bought = true>><<if _p.id === "car1">><<set $PlayerHasCar = true>><</if>><<Refresh>><</if>><</link>></div><<else>><div class="shp-btn-disabled">MONEY</div><</if>><<if $Bank >= +_p.price>><div><<link "<div class='shp-btn'>BANK</div>">><<if $Bank >= +_p.price>><<set $Bank -= +_p.price>><<if _p.inventory>><<set $Inventory[_p.id] to $Inventory[_p.id] or {id:_p.id, name:_p.name, img:_p.img or "", qty:0, desc:_p.desc or ""}>><<if !$Inventory[_p.id].desc and _p.desc>><<set $Inventory[_p.id].desc = _p.desc>><</if>><<set $Inventory[_p.id].qty += 1>><</if>><<set _p.bought = true>><<if _p.id === "car1">><<set $PlayerHasCar = true>><</if>><<Refresh>><</if>><</link>></div><<else>><div class="shp-btn-disabled">BANK</div><</if>></div><</capture>></div></div><</if>><</for>></div></div>
<div class="BottomUiBarCustom">
<<BottomButton "Move">>[[🛍️ Mall|Mall]]<</BottomButton>>
</div><<sound "music" "music.music" true>><<passagebg>><img src="assets/img/misc/MCPC/discord/discord.gif"/><</passagebg>>
<<if $NPCOnlineFriend.afk == true>><<= '<div style="border:1px solid #2f3136;background:#2b2d31;color:#b9bbbe;padding:.5rem 1rem;border-radius:6px;display:flex;align-items:center;gap:.5rem;max-width:960px;min-height:50px;">'+'<span style="width:12px;height:12px;border-radius:50%;background:#80848e;display:inline-block;"></span>'+'<span>'+ $NPCOnlineFriend.name +' is <strong>offline</strong></span>'+'</div>'>><<elseif $NPCOnlineFriend.afk == false>><<= '<div style="border:1px solid #2f3136;background:#2b2d31;color:#dcddde;padding:.5rem 1rem;border-radius:6px;display:flex;align-items:center;gap:.5rem;max-width:300px;">'+'<span style="width:12px;height:12px;border-radius:50%;background:#3ba55d;display:inline-block;"></span>'+'<span>'+ $NPCOnlineFriend.name +' is <strong>online</strong></span>'+'</div>'>><</if>>
<div class="BottomUiBarCustom">
<<BottomButton "Move">><<return [[↩️ Close Discord|MCPC]]>><</BottomButton>>
</div><<set $ShowTopUiBar = false>><<set $ShowBottomUiBar = false>>
<style>
#passages{padding:0!important}
.passage{padding:0!important;max-width:none!important}
.BottomUiBarCustom,#ui-bar,.topUiBar{display:none!important}
#mg-outer{
position:fixed;z-index:5;
background:#07040f;
overflow:hidden;
cursor:default;
}
#mg-hud{
position:absolute;top:0;left:0;right:0;z-index:20;
background:rgba(0,0,0,.82);
backdrop-filter:blur(10px);
border-bottom:1px solid rgba(168,85,247,.12);
padding:7px 18px;
display:flex;align-items:center;gap:16px;
height:48px;box-sizing:border-box;
}
#mg-title-hud{
font-size:1rem;font-weight:900;
letter-spacing:.18em;text-transform:uppercase;
color:rgba(168,85,247,.90);white-space:nowrap;
}
#mg-msg-hud{
flex:1;text-align:center;
font-size:1rem;font-weight:900;
letter-spacing:.1em;text-transform:uppercase;
color:rgba(255,255,255,.70);
transition:color .3s;
}
#mg-score-display{
font-size:1rem;font-weight:900;
letter-spacing:.1em;
color:rgba(251,191,36,.95);
white-space:nowrap;
}
#mg-timerbar-wrap{
position:absolute;bottom:0;left:0;right:0;
height:3px;background:rgba(255,255,255,.05);
}
#mg-timerbar{
height:100%;width:100%;transform-origin:left;
background:linear-gradient(90deg,#a855f7,#ec4899);
transition:background .4s;
}
#mg-grid-wrap{
position:absolute;
top:48px;left:0;right:0;bottom:0;
display:flex;align-items:center;justify-content:center;
padding:16px;
box-sizing:border-box;
}
#mg-grid{
display:grid;
gap:10px;
}
.mg-card{
width:100%;
aspect-ratio:2/3;
cursor:pointer;
perspective:600px;
position:relative;
}
.mg-card-inner{
width:100%;height:100%;
transition:transform .35s cubic-bezier(.4,0,.2,1);
transform-style:preserve-3d;
position:relative;
}
.mg-card.flipped .mg-card-inner,
.mg-card.matched .mg-card-inner{
transform:rotateY(180deg);
}
.mg-card-front,.mg-card-back{
position:absolute;inset:0;
backface-visibility:hidden;
border-radius:8px;
overflow:hidden;
border:1px solid rgba(168,85,247,.20);
}
.mg-card-front{
background:rgba(168,85,247,.06);
display:flex;align-items:center;justify-content:center;
}
.mg-card-front::after{
content:'✦';
font-size:1.6rem;
color:rgba(168,85,247,.25);
}
.mg-card-back{
background:#0d0920;
transform:rotateY(180deg);
display:flex;align-items:center;justify-content:center;
}
.mg-card-back img{
min-width:100%!important;
max-width:100%!important;
min-height:100%!important;
max-height:100%!important;
object-fit:cover!important;
display:block!important;
pointer-events:none!important;
}
.mg-card.matched .mg-card-front,
.mg-card.matched .mg-card-back{
border-color:rgba(251,191,36,.5);
box-shadow:0 0 14px rgba(251,191,36,.25);
}
.mg-card:hover:not(.flipped):not(.matched) .mg-card-front{
border-color:rgba(168,85,247,.45);
background:rgba(168,85,247,.10);
}
#mg-tut{
position:absolute;inset:0;
background:rgba(5,2,12,.96);
display:flex;flex-direction:column;
align-items:center;justify-content:center;
gap:18px;padding:32px;z-index:50;
}
#mg-tut-title{
font-size:1.8rem;font-weight:950;
color:rgba(192,132,252,.95);letter-spacing:.14em;
text-transform:uppercase;text-align:center;
}
#mg-tut-body{
font-size:1.10rem;color:rgba(220,200,255,.80);
text-align:center;line-height:1.78;
max-width:520px;font-weight:700;
letter-spacing:.02em;white-space:pre-line;
}
#mg-tut-step{
font-size:.85rem;color:rgba(168,85,247,.70);
letter-spacing:.16em;font-weight:900;
}
.mg-tut-dots{display:flex;gap:9px;align-items:center;}
.mg-tut-dot{
width:8px;height:8px;border-radius:50%;
background:rgba(168,85,247,.20);
transition:background .25s,box-shadow .25s;
}
.mg-tut-dot.active{background:rgba(168,85,247,.85);box-shadow:0 0 8px rgba(168,85,247,.60);}
.mg-tut-dot.done{background:rgba(168,85,247,.45);}
#mg-tut-preview{
display:grid;
gap:6px;
margin:4px 0;
}
.mg-tut-card-demo{
width:52px;height:78px;
border-radius:6px;
border:1px solid rgba(168,85,247,.22);
background:rgba(168,85,247,.06);
display:flex;align-items:center;justify-content:center;
font-size:1.2rem;color:rgba(168,85,247,.35);
}
.mg-tut-card-demo.show{
background:rgba(168,85,247,.14);
border-color:rgba(168,85,247,.50);
color:rgba(192,132,252,.80);
}
.mg-tut-card-demo.matched-demo{
border-color:rgba(251,191,36,.55);
box-shadow:0 0 10px rgba(251,191,36,.25);
color:rgba(251,191,36,.80);
}
#mg-tut-btn{
padding:14px 44px;border-radius:11px;
border:1px solid rgba(168,85,247,.50);
background:rgba(168,85,247,.14);
color:rgba(192,132,252,.95);font-weight:950;
font-size:1.05rem;letter-spacing:.14em;
cursor:pointer;text-transform:uppercase;
transition:background .15s,border-color .15s;
user-select:none;
}
#mg-tut-btn:hover{background:rgba(168,85,247,.24);border-color:rgba(168,85,247,.70);}
#mg-lvl-select{
position:absolute;inset:0;
background:rgba(5,2,12,.96);
display:none;flex-direction:column;
align-items:center;justify-content:center;
gap:20px;z-index:50;
}
#mg-lvl-title{
font-size:1.8rem;font-weight:950;
color:rgba(192,132,252,.95);letter-spacing:.14em;
text-transform:uppercase;
}
#mg-lvl-sub{
font-size:1.05rem;color:rgba(220,200,255,.65);
letter-spacing:.08em;text-align:center;
}
.mg-lvl-btns{display:flex;gap:12px;flex-wrap:wrap;justify-content:center;}
.mg-lvl-btn{
padding:16px 28px;border-radius:10px;
border:1px solid rgba(168,85,247,.40);
background:rgba(168,85,247,.10);
color:rgba(192,132,252,.90);font-weight:900;
font-size:1.05rem;letter-spacing:.12em;
cursor:pointer;text-transform:uppercase;
transition:background .15s,border-color .15s,transform .1s;
user-select:none;
display:flex;flex-direction:column;align-items:center;gap:6px;
}
.mg-lvl-btn:hover{
background:rgba(168,85,247,.22);
border-color:rgba(168,85,247,.65);
transform:translateY(-2px);
}
.mg-lvl-btn span{
font-size:.80rem;color:rgba(192,132,252,.65);
letter-spacing:.08em;
}
#mg-pay-confirm{
position:absolute;inset:0;
background:rgba(5,2,12,.97);
display:none;flex-direction:column;
align-items:center;justify-content:center;
gap:22px;z-index:60;
}
#mg-pay-title{
font-size:1.7rem;font-weight:950;
color:rgba(192,132,252,.95);letter-spacing:.14em;
text-transform:uppercase;
}
#mg-pay-msg{
font-size:1.05rem;color:rgba(220,200,255,.75);
letter-spacing:.06em;text-align:center;line-height:1.7;
}
#mg-pay-balance{
font-size:1rem;color:rgba(251,191,36,.85);
letter-spacing:.08em;font-weight:900;
}
.mg-pay-btns{display:flex;gap:16px;}
.mg-pay-btn{
padding:14px 34px;border-radius:10px;
font-size:1rem;font-weight:950;
letter-spacing:.12em;text-transform:uppercase;
cursor:pointer;user-select:none;
transition:background .15s,border-color .15s,transform .1s;
display:flex;flex-direction:column;align-items:center;gap:4px;
}
.mg-pay-btn:hover{transform:translateY(-2px);}
#mg-pay-confirm-btn{
border:1px solid rgba(168,85,247,.50);
background:rgba(168,85,247,.14);
color:rgba(192,132,252,.95);
}
#mg-pay-confirm-btn:hover{background:rgba(168,85,247,.26);}
#mg-pay-cancel-btn{
border:1px solid rgba(255,80,80,.35);
background:rgba(255,80,80,.08);
color:rgba(255,140,140,.80);
}
#mg-pay-cancel-btn:hover{background:rgba(255,80,80,.18);}
#mg-infinite-label{
display:flex;align-items:center;gap:12px;cursor:pointer;
font-size:1rem;color:rgba(192,132,252,.75);letter-spacing:.08em;
margin-top:4px;user-select:none;
}
#mg-infinite-toggle{
width:48px;height:26px;border-radius:999px;
background:rgba(255,255,255,.10);border:1px solid rgba(255,255,255,.15);
position:relative;cursor:pointer;transition:background .16s,border-color .16s;
flex-shrink:0;
}
#mg-infinite-toggle.on{
background:rgba(168,85,247,.25);border-color:rgba(168,85,247,.55);
}
#mg-infinite-knob{
position:absolute;top:50%;left:3px;
width:20px;height:20px;border-radius:999px;
background:rgba(255,255,255,.50);
transform:translateY(-50%);
transition:transform .16s ease,background .16s ease;
}
#mg-infinite-toggle.on #mg-infinite-knob{
transform:translateY(-50%) translateX(22px);
background:rgba(168,85,247,.90);
}
#mg-done-overlay{
position:absolute;inset:0;z-index:40;
background:rgba(5,2,12,.92);
display:none;flex-direction:column;
align-items:center;justify-content:center;
gap:14px;
}
#mg-done-title{
font-size:1.7rem;font-weight:950;
color:rgba(192,132,252,.95);letter-spacing:.14em;
text-transform:uppercase;
}
#mg-done-val{
font-size:4rem;font-weight:950;
color:rgba(251,191,36,.98);line-height:1;
text-shadow:0 0 30px rgba(251,191,36,.40);
}
#mg-done-sub{
font-size:.88rem;color:rgba(255,255,255,.50);
letter-spacing:.14em;font-weight:900;
text-transform:uppercase;margin-bottom:8px;
}
#mg-done-stats{
display:flex;gap:18px;align-items:center;
background:rgba(168,85,247,.06);
border:1px solid rgba(168,85,247,.18);
border-radius:14px;
padding:14px 28px;margin-bottom:4px;
}
.mg-done-stat{
display:flex;flex-direction:column;
align-items:center;gap:4px;
}
.mg-done-stat-val{
font-size:1.6rem;font-weight:950;
color:rgba(226,217,255,.92);letter-spacing:.04em;
}
.mg-done-stat-label{
font-size:.78rem;font-weight:900;
letter-spacing:.12em;text-transform:uppercase;
color:rgba(168,85,247,.65);
}
.mg-done-divider{
width:1px;height:40px;
background:rgba(168,85,247,.18);
}
#mg-done-btn{
margin-top:6px;
padding:16px 52px;border-radius:12px;
border:1px solid rgba(168,85,247,.50);
background:rgba(168,85,247,.14);
color:rgba(192,132,252,.95);font-weight:950;
font-size:1.05rem;letter-spacing:.14em;
cursor:pointer;text-transform:uppercase;
transition:background .15s,border-color .15s,transform .1s;
user-select:none;
}
#mg-done-btn:hover{
background:rgba(168,85,247,.26);
border-color:rgba(168,85,247,.70);
transform:translateY(-1px);
}
</style>
<div id="mg-outer">
<div id="mg-hud">
<div id="mg-title-hud">Memory</div>
<div id="mg-msg-hud">Find the pairs...</div>
<div id="mg-score-display">✦ 0</div>
<div id="mg-timerbar-wrap"><div id="mg-timerbar"></div></div>
</div>
<button id="mg-quit-btn" style="display:none;position:absolute;top:56px;right:12px;z-index:25;background:rgba(0,0,0,.7);border:1px solid rgba(255,255,255,.15);border-radius:50%;width:30px;height:30px;color:rgba(255,255,255,.50);font-size:14px;cursor:pointer;line-height:1;" onclick="window.MemoryGame.quitGame()">✕</button>
<div id="mg-countdown" style="display:none;position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);z-index:25;font-size:8rem;font-weight:950;color:rgba(168,85,247,0.70);letter-spacing:.1em;pointer-events:none;"></div>
<div id="mg-grid-wrap">
<div id="mg-grid"></div>
</div>
<div id="mg-tut" style="display:none">
<div class="mg-tut-dots">
<div class="mg-tut-dot active" id="mg-dot-0"></div>
<div class="mg-tut-dot" id="mg-dot-1"></div>
<div class="mg-tut-dot" id="mg-dot-2"></div>
</div>
<div id="mg-tut-title">Memory Game</div>
<div id="mg-tut-preview"></div>
<div id="mg-tut-body">loading...</div>
<div id="mg-tut-step">STEP 1 / 3</div>
<div id="mg-tut-btn" onclick="window.MemoryGame.tutNext()">NEXT →</div>
</div>
<div id="mg-lvl-select">
<div id="mg-lvl-title">Memory Game</div>
<div id="mg-lvl-sub">Choose your difficulty. Win $5 per pair × multiplier.</div>
<div class="mg-lvl-btns">
<button class="mg-lvl-btn" onclick="window.MemoryGame.tryStartLevel(1)">4×4<span id="mg-lvl-entry-1" style="transition:opacity .2s;white-space:nowrap;">Entry $10</span></button>
<button class="mg-lvl-btn" onclick="window.MemoryGame.tryStartLevel(2)">4×5<span id="mg-lvl-entry-2" style="transition:opacity .2s;white-space:nowrap;">Entry $30</span></button>
<button class="mg-lvl-btn" onclick="window.MemoryGame.tryStartLevel(3)">4×6<span id="mg-lvl-entry-3" style="transition:opacity .2s;white-space:nowrap;">Entry $60</span></button>
<button class="mg-lvl-btn" onclick="window.MemoryGame.tryStartLevel(4)">4×7<span id="mg-lvl-entry-4" style="transition:opacity .2s;white-space:nowrap;">Entry $90</span></button>
<button class="mg-lvl-btn" onclick="window.MemoryGame.tryStartLevel(5)">4×8<span id="mg-lvl-entry-5" style="transition:opacity .2s;white-space:nowrap;">Entry $120</span></button>
</div>
<div style="display:flex;gap:12px;margin-top:4px;align-items:center;">
<button class="mg-lvl-btn" style="border-color:rgba(168,85,247,.28);color:rgba(168,85,247,.70);padding:12px 22px;" onclick="window.MemoryGame.showTutorial()">?<span>How to play</span></button>
<button class="mg-lvl-btn" style="border-color:rgba(255,80,80,.28);color:rgba(255,140,140,.70);padding:12px 22px;" onclick="window.MemoryGame.returnCasino()">←<span>Return</span></button>
</div>
<label id="mg-infinite-label">
<div id="mg-infinite-toggle" onclick="window.MemoryGame.toggleInfinite(this)">
<div id="mg-infinite-knob"></div>
</div>
<span>Infinite Time</span>
</label>
<div id="mg-infinite-msg" style="visibility:hidden;max-width:340px;text-align:center;font-size:.82rem;color:rgba(168,85,247,.65);line-height:1.6;font-weight:700;letter-spacing:.03em;border:1px solid rgba(168,85,247,.18);border-radius:10px;padding:10px 16px;background:rgba(168,85,247,.06);">∞ Infinite mode is free to play but awards no money. Perfect for a relaxed game with no pressure.</div>
</div>
<div id="mg-pay-confirm">
<div id="mg-pay-title">Entry Fee</div>
<div id="mg-pay-msg">Loading...</div>
<div id="mg-pay-balance">Balance: $0</div>
<div class="mg-pay-btns">
<button class="mg-pay-btn" id="mg-pay-confirm-btn" onclick="window.MemoryGame.confirmPay()">Pay & Play</button>
<button class="mg-pay-btn" id="mg-pay-cancel-btn" onclick="window.MemoryGame.cancelPay()">Cancel</button>
</div>
</div>
<div id="mg-done-overlay">
<div id="mg-done-title">Session Complete</div>
<div id="mg-done-val">+$0</div>
<div id="mg-done-stats">
<div class="mg-done-stat">
<div class="mg-done-stat-val" id="mg-stat-pairs">0</div>
<div class="mg-done-stat-label">Pairs Found</div>
</div>
<div class="mg-done-divider"></div>
<div class="mg-done-stat">
<div class="mg-done-stat-val" id="mg-stat-mult">×1</div>
<div class="mg-done-stat-label">Multiplier</div>
</div>
<div class="mg-done-divider"></div>
<div class="mg-done-stat">
<div class="mg-done-stat-val" id="mg-stat-pp">$0</div>
<div class="mg-done-stat-label">Money Won</div>
</div>
</div>
<div id="mg-done-sub">Casino Winnings</div>
<div id="mg-done-btn" onclick="window.MemoryGame.returnCasino()">RETURN ›</div>
</div>
</div>
<<script>>
(function(){
"use strict";
window.MemoryGame = window.MemoryGame || {};
var MG = window.MemoryGame;
var CFG = {
PREVIEW_DURATION: 5,
SESSION_DURATION: { 1:30, 2:35, 3:40, 4:45, 5:50 },
IMG_BASE: "assets/img/minigames/meditation/",
LEVEL_IMG_COUNT: { 1:19, 2:21, 3:28, 4:29, 5:32 },
GRID: {
1:{cols:4,rows:4},
2:{cols:5,rows:4},
3:{cols:6,rows:4},
4:{cols:7,rows:4},
5:{cols:8,rows:4}
},
MULTIPLIER: { 1:1, 2:2, 3:3, 4:4, 5:5 },
MONEY_PER_PAIR: 5,
ENTRY_FEE: { 1:10, 2:30, 3:60, 4:90, 5:120 }
};
var AC=null,masterGain=null,musicGain=null,sfxGain=null;
var dronOsc=null,dronGain=null,dron2Osc=null,dron2Gain=null;
var bassOsc=null,bassGain=null,bassFilter=null;
var padNodes=[],arpNodes=[];
var ambLoopId=null,arpLoopId=null,bassLoopId=null,modLoopId=null,pulseLoopId=null;
var BPM=72,BEAT=60/BPM,SIXTEENTH=BEAT/4;
var bassPatIdx=0,padIdx=0,arpPatIdx=0,arpNoteIdx=0;
function initAudio(){
if(AC)return;
try{
AC=new(window.AudioContext||window.webkitAudioContext)();
masterGain=AC.createGain();masterGain.gain.value=0.78;masterGain.connect(AC.destination);
musicGain=AC.createGain();musicGain.gain.value=0.50;musicGain.connect(masterGain);
sfxGain=AC.createGain();sfxGain.gain.value=0.90;sfxGain.connect(masterGain);
}catch(e){}
}
function makeOsc(type,freq,vol,dur,dest,t){
if(!AC)return;dest=dest||sfxGain;t=t||AC.currentTime;
var o=AC.createOscillator(),g=AC.createGain();
o.type=type;o.frequency.value=freq;
g.gain.setValueAtTime(0,t);g.gain.linearRampToValueAtTime(vol,t+0.01);
g.gain.exponentialRampToValueAtTime(0.0001,t+dur);
o.connect(g);g.connect(dest);o.start(t);o.stop(t+dur+0.02);
}
function makeNoise(freq,q,vol,dur,dest,t){
if(!AC)return;dest=dest||sfxGain;t=t||AC.currentTime;
var sz=Math.floor(AC.sampleRate*Math.min(dur,2));
var buf=AC.createBuffer(1,sz,AC.sampleRate);
var d=buf.getChannelData(0);for(var i=0;i<sz;i++)d[i]=Math.random()*2-1;
var src=AC.createBufferSource(),f=AC.createBiquadFilter(),g=AC.createGain();
f.type='bandpass';f.frequency.value=freq;f.Q.value=q||1.2;
g.gain.setValueAtTime(0,t);g.gain.linearRampToValueAtTime(vol,t+0.012);
g.gain.exponentialRampToValueAtTime(0.0001,t+dur);
src.buffer=buf;src.connect(f);f.connect(g);g.connect(dest);src.start(t);src.stop(t+dur+0.02);
}
var BASS_PATTERN=[{note:55,dur:2,vel:1.0},{note:0,dur:1,vel:0},{note:55,dur:1,vel:0.6},{note:0,dur:2,vel:0},{note:82.4,dur:1,vel:0.9},{note:0,dur:1,vel:0},{note:73.4,dur:2,vel:0.85},{note:0,dur:2,vel:0},{note:55,dur:2,vel:1.0},{note:0,dur:1,vel:0},{note:65.4,dur:1,vel:0.7},{note:0,dur:2,vel:0},{note:82.4,dur:3,vel:0.9},{note:0,dur:1,vel:0}];
var PAD_CHORDS=[[110,130.8,164.8,220],[98,123.5,164.8,196],[110,138.6,185,220],[123.5,164.8,220,261.6],[98,130.8,164.8,246.9],[110,146.8,196,220]];
var ARP_PATTERNS=[[220,329.6,440,329.6,261.6,392,523.2,392],[440,329.6,261.6,220,261.6,329.6,440,523.2],[329.6,220,261.6,392,329.6,261.6,220,164.8],[523.2,440,392,329.6,261.6,220,261.6,329.6]];
function startAmbience(){
if(!AC||dronOsc)return;
dronOsc=AC.createOscillator();dronGain=AC.createGain();
var df=AC.createBiquadFilter();df.type='lowpass';df.frequency.value=140;df.Q.value=3.5;
dronOsc.type='sawtooth';dronOsc.frequency.value=55;
var dLFO=AC.createOscillator(),dLFOg=AC.createGain();
dLFO.frequency.value=0.05;dLFOg.gain.value=12;dLFO.connect(dLFOg);dLFOg.connect(dronOsc.frequency);dLFO.start();
dronGain.gain.setValueAtTime(0,AC.currentTime);dronGain.gain.linearRampToValueAtTime(0.18,AC.currentTime+3.0);
dronOsc.connect(df);df.connect(dronGain);dronGain.connect(musicGain);dronOsc.start();
dron2Osc=AC.createOscillator();dron2Gain=AC.createGain();
var d2f=AC.createBiquadFilter();d2f.type='bandpass';d2f.frequency.value=440;d2f.Q.value=2.2;
dron2Osc.type='triangle';dron2Osc.frequency.value=220;
var trem=AC.createOscillator(),tremg=AC.createGain();
trem.frequency.value=4.2;tremg.gain.value=0.04;trem.connect(tremg);tremg.connect(dron2Gain.gain);trem.start();
dron2Gain.gain.setValueAtTime(0,AC.currentTime);dron2Gain.gain.linearRampToValueAtTime(0.07,AC.currentTime+4.0);
dron2Osc.connect(d2f);d2f.connect(dron2Gain);dron2Gain.connect(musicGain);dron2Osc.start();
bassOsc=AC.createOscillator();bassGain=AC.createGain();bassFilter=AC.createBiquadFilter();
bassFilter.type='lowpass';bassFilter.frequency.value=340;bassFilter.Q.value=3.5;
bassOsc.type='square';bassOsc.frequency.value=55;bassGain.gain.value=0;
bassOsc.connect(bassFilter);bassFilter.connect(bassGain);bassGain.connect(musicGain);bassOsc.start();
function bassStep(){
if(!AC||!bassGain||!bassOsc)return;
var step=BASS_PATTERN[bassPatIdx%BASS_PATTERN.length];bassPatIdx++;
var t=AC.currentTime,durMs=step.dur*SIXTEENTH*1000;
if(step.note>0&&step.vel>0){
bassOsc.frequency.setValueAtTime(step.note,t);
bassGain.gain.cancelScheduledValues(t);bassGain.gain.setValueAtTime(0,t);
bassGain.gain.linearRampToValueAtTime(0.24*step.vel,t+0.025);
bassGain.gain.exponentialRampToValueAtTime(0.0001,t+step.dur*SIXTEENTH*0.85);
}
bassLoopId=setTimeout(bassStep,durMs);
}
setTimeout(bassStep,900);
function playPad(){
if(!AC||!musicGain)return;
var freqs=PAD_CHORDS[padIdx%PAD_CHORDS.length];padIdx++;
freqs.forEach(function(fr,vi){
var o=AC.createOscillator(),g=AC.createGain(),flt=AC.createBiquadFilter();
flt.type='lowpass';flt.frequency.value=1600;flt.Q.value=0.6;
o.type=vi<2?'sine':'triangle';o.frequency.value=fr*(1+(vi%2===0?1:-1)*0.003);
var t=AC.currentTime,atk=1.8+Math.random()*0.6,hold=5.0+Math.random()*1.5,rel=2.8;
g.gain.setValueAtTime(0,t);g.gain.linearRampToValueAtTime(0.052,t+atk);
g.gain.setValueAtTime(0.052,t+atk+hold);g.gain.exponentialRampToValueAtTime(0.0001,t+atk+hold+rel);
o.connect(flt);flt.connect(g);g.connect(musicGain);o.start(t);o.stop(t+atk+hold+rel+0.1);
padNodes.push(o);
});
ambLoopId=setTimeout(playPad,7000+Math.random()*1500);
}
setTimeout(playPad,600);
function playArp(){
if(!AC||!musicGain)return;
var pat=ARP_PATTERNS[arpPatIdx%ARP_PATTERNS.length];
var freq=pat[arpNoteIdx%pat.length];arpNoteIdx++;
if(arpNoteIdx>=pat.length){arpNoteIdx=0;if(Math.random()<0.45)arpPatIdx++;}
var o=AC.createOscillator(),g=AC.createGain(),hpf=AC.createBiquadFilter();
hpf.type='highpass';hpf.frequency.value=500;o.type='sine';o.frequency.value=freq;
var t=AC.currentTime;
g.gain.setValueAtTime(0,t);g.gain.linearRampToValueAtTime(0.062,t+0.007);
g.gain.exponentialRampToValueAtTime(0.008,t+0.6);g.gain.exponentialRampToValueAtTime(0.0001,t+1.4);
o.connect(hpf);hpf.connect(g);g.connect(musicGain);o.start(t);o.stop(t+1.5);
var isRest=Math.random()<0.18,steps=isRest?2:1,swing=arpNoteIdx%2===0?1.0:0.88;
arpLoopId=setTimeout(playArp,SIXTEENTH*steps*swing*1000);
}
setTimeout(playArp,1600);
function modTick(){
if(!AC||!musicGain)return;
var t=AC.currentTime;
var sz=Math.floor(AC.sampleRate*8),buf=AC.createBuffer(1,sz,AC.sampleRate),d=buf.getChannelData(0);
for(var i=0;i<sz;i++)d[i]=Math.random()*2-1;
var src=AC.createBufferSource(),f=AC.createBiquadFilter(),g=AC.createGain();
f.type='bandpass';f.frequency.setValueAtTime(120,t);f.frequency.exponentialRampToValueAtTime(1800,t+7.5);f.Q.value=5;
g.gain.setValueAtTime(0,t);g.gain.linearRampToValueAtTime(0.038,t+1.2);
g.gain.setValueAtTime(0.038,t+5.5);g.gain.exponentialRampToValueAtTime(0.0001,t+8);
src.buffer=buf;src.connect(f);f.connect(g);g.connect(musicGain);src.start(t);src.stop(t+8.2);
modLoopId=setTimeout(modTick,9000+Math.random()*5000);
}
setTimeout(modTick,4000);
function pulseTick(){
if(!AC||!musicGain)return;
var t=AC.currentTime;
function kick(delay,vol){
var o=AC.createOscillator(),g=AC.createGain();o.type='sine';
o.frequency.setValueAtTime(120,t+delay);o.frequency.exponentialRampToValueAtTime(38,t+delay+0.18);
g.gain.setValueAtTime(0,t+delay);g.gain.linearRampToValueAtTime(vol,t+delay+0.008);
g.gain.exponentialRampToValueAtTime(0.0001,t+delay+0.28);
o.connect(g);g.connect(musicGain);o.start(t+delay);o.stop(t+delay+0.3);
}
kick(0,0.20);kick(0.18,0.12);
pulseLoopId=setTimeout(pulseTick,BEAT*2*1000);
}
setTimeout(pulseTick,1200);
}
function stopAmbience(){
function fadeStop(osc,gain){
if(!osc||!gain)return;
try{gain.gain.setTargetAtTime(0,AC.currentTime,0.22);setTimeout(function(){try{osc.stop();}catch(e){}},500);}catch(e){}
}
fadeStop(dronOsc,dronGain);dronOsc=null;
fadeStop(dron2Osc,dron2Gain);dron2Osc=null;
fadeStop(bassOsc,bassGain);bassOsc=null;
if(ambLoopId){clearTimeout(ambLoopId);ambLoopId=null;}
if(arpLoopId){clearTimeout(arpLoopId);arpLoopId=null;}
if(bassLoopId){clearTimeout(bassLoopId);bassLoopId=null;}
if(modLoopId){clearTimeout(modLoopId);modLoopId=null;}
if(pulseLoopId){clearTimeout(pulseLoopId);pulseLoopId=null;}
padNodes.forEach(function(o){try{o.stop();}catch(e){}});padNodes=[];
arpNodes.forEach(function(o){try{o.stop();}catch(e){}});arpNodes=[];
bassPatIdx=0;padIdx=0;arpPatIdx=0;arpNoteIdx=0;
}
function sfxFlip(){if(!AC)return;makeOsc('sine',660,0.06,0.10,sfxGain);}
function sfxMatch(){
if(!AC)return;var t=AC.currentTime;
[440,550,660,880].forEach(function(f,i){makeOsc('sine',f,0.08,0.35,sfxGain,t+i*0.06);});
makeNoise(1200,2,0.05,0.18,sfxGain,t);
}
function sfxMiss(){if(!AC)return;makeOsc('sawtooth',140,0.05,0.25,sfxGain);}
function sfxEnd(pts){
if(!AC)return;var t=AC.currentTime;
var notes=pts>6?[220,261.6,329.6,392,440,523.2]:pts>3?[220,261.6,329.6,392]:[220,261.6,329.6];
notes.forEach(function(f,i){makeOsc('sine',f,0.10,1.0,sfxGain,t+i*0.12);});
}
function sfxTut(){if(!AC)return;makeOsc('sine',520,0.06,0.12,sfxGain);}
var TUT_STEPS=[
{
title:'MEMORY GAME',
body:'A grid of face-down cards is placed before you.\nEach image appears exactly twice in the grid.\nYour goal: find all matching pairs before time runs out.',
demo:'grid'
},
{
title:'HOW TO PLAY',
body:'You have 5 seconds to memorize the cards before they flip back.\nClick a card to reveal it.\nClick a second card — if they match, you score a point!\nIf not, both flip back face-down.',
demo:'flip'
},
{
title:'TIME & REWARDS',
body:'Pay an entry fee to play. Each pair found = $5 × level multiplier.\nHigher difficulty = bigger multiplier = more money!\nComplete all pairs before time runs out.',
demo:'score'
}
];
var tutStep=0;
function updateTutDots(){
for(var i=0;i<TUT_STEPS.length;i++){
var d=document.getElementById('mg-dot-'+i);
if(!d)continue;
d.className='mg-tut-dot';
if(i===tutStep)d.classList.add('active');
else if(i<tutStep)d.classList.add('done');
}
}
function buildTutDemo(type){
var p=document.getElementById('mg-tut-preview');
if(!p)return;
if(type==='grid'){
p.style.gridTemplateColumns='repeat(4,52px)';
p.innerHTML='';
for(var i=0;i<8;i++){
var c=document.createElement('div');
c.className='mg-tut-card-demo';c.textContent='✦';p.appendChild(c);
}
} else if(type==='flip'){
p.style.gridTemplateColumns='repeat(4,52px)';
p.innerHTML='';
var states=['show','','show',''];
for(var i=0;i<8;i++){
var c=document.createElement('div');
c.className='mg-tut-card-demo'+(states[i%4]?' '+states[i%4]:'');
c.textContent=states[i%4]==='show'?'★':'✦';
p.appendChild(c);
}
} else {
p.style.gridTemplateColumns='repeat(4,52px)';
p.innerHTML='';
for(var i=0;i<8;i++){
var c=document.createElement('div');
var isMatch=i<4;
c.className='mg-tut-card-demo'+(isMatch?' matched-demo':' show');
c.textContent=isMatch?'✦':'★';
p.appendChild(c);
}
}
}
function showTutorial(){
tutStep=0;
var sel=document.getElementById('mg-lvl-select');
if(sel)sel.style.display='none';
var tut=document.getElementById('mg-tut');
if(tut)tut.style.display='flex';
updateTutStep();
}
function updateTutStep(){
var step=TUT_STEPS[tutStep];if(!step)return;
var title=document.getElementById('mg-tut-title');
var body=document.getElementById('mg-tut-body');
var stp=document.getElementById('mg-tut-step');
var btn=document.getElementById('mg-tut-btn');
if(title)title.textContent=step.title;
if(body)body.textContent=step.body;
if(stp)stp.textContent='STEP '+(tutStep+1)+' / '+TUT_STEPS.length;
if(btn)btn.textContent=tutStep===TUT_STEPS.length-1?'GOT IT →':'NEXT →';
buildTutDemo(step.demo);
sfxTut();
updateTutDots();
}
function tutNext(){
tutStep++;
if(tutStep>=TUT_STEPS.length){
var tut=document.getElementById('mg-tut');
if(tut)tut.style.display='none';
var sel=document.getElementById('mg-lvl-select');
if(sel)sel.style.display='flex';
return;
}
updateTutStep();
}
function toggleInfinite(el){
el.classList.toggle('on');
infiniteMode=el.classList.contains('on');
var msg=document.getElementById('mg-infinite-msg');
var sub=document.getElementById('mg-lvl-sub');
for(var i=1;i<=5;i++){
var sp=document.getElementById('mg-lvl-entry-'+i);
if(sp) sp.style.opacity=infiniteMode?'0':'1';
}
if(msg) msg.style.visibility=infiniteMode?'visible':'hidden';
if(sub) sub.textContent=infiniteMode?'Choose your difficulty.':'Choose your difficulty. Win $5 per pair × multiplier.';
}
var currentLevel=1,infiniteMode=false,pendingLevel=0;
var cards=[],flipped=[],matched=0,score=0;
var canFlip=true,sessionDone=false;
var timeLeft=0,timerInterval=null;
function tryStartLevel(lvl){
if(infiniteMode){
pendingLevel=lvl;
var sel=document.getElementById('mg-lvl-select');
if(sel)sel.style.display='none';
startLevel(lvl);
return;
}
var fee=CFG.ENTRY_FEE[lvl]||10;
var money=State.variables.Money||0;
pendingLevel=lvl;
var pay=document.getElementById('mg-pay-confirm');
var msg=document.getElementById('mg-pay-msg');
var bal=document.getElementById('mg-pay-balance');
var btn=document.getElementById('mg-pay-confirm-btn');
if(msg)msg.textContent='Level '+lvl+' requires a $'+fee+' entry fee.\nWin $'+(CFG.MONEY_PER_PAIR*CFG.MULTIPLIER[lvl])+' per pair found.';
if(bal)bal.textContent='Your balance: $'+money;
if(btn){
if(money<fee){
btn.textContent='Not enough money';
btn.style.opacity='0.35';
btn.style.pointerEvents='none';
} else {
btn.textContent='Pay $'+fee+' & Play';
btn.style.opacity='';
btn.style.pointerEvents='';
}
}
var sel=document.getElementById('mg-lvl-select');
if(sel)sel.style.display='none';
if(pay)pay.style.display='flex';
}
function confirmPay(){
var fee=CFG.ENTRY_FEE[pendingLevel]||10;
var money=State.variables.Money||0;
if(money<fee)return;
State.variables.Money=money-fee;
var pay=document.getElementById('mg-pay-confirm');
if(pay)pay.style.display='none';
startLevel(pendingLevel);
}
function cancelPay(){
var pay=document.getElementById('mg-pay-confirm');
if(pay)pay.style.display='none';
var sel=document.getElementById('mg-lvl-select');
if(sel)sel.style.display='flex';
}
function shuffle(arr){
for(var i=arr.length-1;i>0;i--){
var j=Math.floor(Math.random()*(i+1));
var tmp=arr[i];arr[i]=arr[j];arr[j]=tmp;
}
return arr;
}
function pickImages(level,count){
var total=CFG.LEVEL_IMG_COUNT[level]||12;
var indices=[];
for(var i=1;i<=total;i++)indices.push(i);
shuffle(indices);
var chosen=indices.slice(0,count);
return chosen.map(function(n){
return CFG.IMG_BASE+level+'/'+n+'.webp';
});
}
function buildGrid(level){
var g=CFG.GRID[level];
var cols=g.cols,rows=g.rows;
var pairs=(cols*rows)/2;
var imgs=pickImages(level,pairs);
imgs.forEach(function(src){
if(window.setup&&setup._galCapture) setup._galCapture(src,'img');
});
var deck=imgs.concat(imgs);
shuffle(deck);
var grid=document.getElementById('mg-grid');
var wrap=document.getElementById('mg-grid-wrap');
if(!grid||!wrap)return;
var wrapW=wrap.clientWidth-32;
var wrapH=wrap.clientHeight-32;
var gapPx=10;
var cardW=Math.floor((wrapW-(cols-1)*gapPx)/cols);
var cardH=Math.floor((wrapH-(rows-1)*gapPx)/rows);
var cardSize=Math.min(cardW,Math.floor(cardH*2/3));
grid.style.gridTemplateColumns='repeat('+cols+','+cardSize+'px)';
grid.style.gridTemplateRows='repeat('+rows+','+Math.floor(cardSize*3/2)+'px)';
grid.innerHTML='';
cards=[];
deck.forEach(function(src,idx){
var outer=document.createElement('div');
outer.className='mg-card';
outer.dataset.idx=idx;
outer.dataset.src=src;
var inner=document.createElement('div');
inner.className='mg-card-inner';
var front=document.createElement('div');
front.className='mg-card-front';
var back=document.createElement('div');
back.className='mg-card-back';
var img=document.createElement('img');
img.src=src;img.alt='';
back.appendChild(img);
inner.appendChild(front);inner.appendChild(back);
outer.appendChild(inner);
outer.addEventListener('click',function(){onCardClick(outer);});
grid.appendChild(outer);
cards.push(outer);
});
}
function onCardClick(card){
if(!canFlip||sessionDone)return;
if(card.classList.contains('flipped')||card.classList.contains('matched'))return;
card.classList.add('flipped');
sfxFlip();
flipped.push(card);
if(flipped.length===2){
canFlip=false;
var a=flipped[0],b=flipped[1];
if(a.dataset.src===b.dataset.src){
setTimeout(function(){
a.classList.add('matched');b.classList.add('matched');
a.classList.remove('flipped');b.classList.remove('flipped');
matched++;score++;
sfxMatch();
updateHUD();
flipped=[];canFlip=true;
if(matched===(cards.length/2))endSession(true);
},400);
} else {
var cardA = a, cardB = b;
flipped = [];
setTimeout(function(){
canFlip = true;
}, 360);
setTimeout(function(){
cardA.classList.remove('flipped');
cardB.classList.remove('flipped');
sfxMiss();
}, 900);
}
}
}
function setMsg(txt,col){
var m=document.getElementById('mg-msg-hud');
if(m){m.textContent=txt;m.style.color=col||'rgba(255,255,255,0.22)';}
}
function updateHUD(){
var sc=document.getElementById('mg-score-display');
if(sc)sc.textContent='✦ '+score;
}
function startTimer(){
timeLeft=CFG.SESSION_DURATION[currentLevel]||30;
if(timerInterval)clearInterval(timerInterval);
timerInterval=setInterval(function(){
timeLeft--;
var pct=Math.max(0,timeLeft/(CFG.SESSION_DURATION[currentLevel]||30));
var tb=document.getElementById('mg-timerbar');
if(tb){
tb.style.width=(pct*100)+'%';
tb.style.background=pct>0.5
?'linear-gradient(90deg,#a855f7,#ec4899)'
:pct>0.25?'linear-gradient(90deg,#f59e0b,#ec4899)'
:'linear-gradient(90deg,#ef4444,#f87171)';
}
if(timeLeft<=0){clearInterval(timerInterval);endSession(false);}
},1000);
}
function endSession(completed){
if(sessionDone)return;
sessionDone=true;
if(timerInterval){clearInterval(timerInterval);timerInterval=null;}
stopAmbience();
sfxEnd(score);
var mult=CFG.MULTIPLIER[currentLevel]||1;
var moneyGain=infiniteMode?0:score*mult*CFG.MONEY_PER_PAIR;
if(moneyGain>0){
State.variables.Money=(State.variables.Money||0)+moneyGain;
State.variables.Energy=(State.variables.Energy||0)-1;
State.variables.Time=(State.variables.Time||0)+1;
}
State.variables.StartStory=true;
var done=document.getElementById('mg-done-overlay');
if(done){
done.style.display='flex';
var dv=document.getElementById('mg-done-val');
if(dv)dv.textContent='+$'+moneyGain;
var sp=document.getElementById('mg-stat-pairs');if(sp)sp.textContent=score;
var sm=document.getElementById('mg-stat-mult');if(sm)sm.textContent='×'+mult;
var spp=document.getElementById('mg-stat-pp');if(spp)spp.textContent='$'+moneyGain;
var sub=document.getElementById('mg-done-sub');
if(sub)sub.textContent=completed?'All pairs found!':'Time\'s up!';
}
setMsg(completed?'ALL PAIRS FOUND!':'TIME\'S UP','rgba(168,85,247,0.70)');
}
function returnCasino(){
State.variables.ShowTopUiBar=true;
State.variables.ShowBottomUiBar=true;
Engine.play(State.variables.return||'Casino');
}
function quitGame(){
sessionDone=true;
if(timerInterval){clearInterval(timerInterval);timerInterval=null;}
stopAmbience();
returnCasino();
}
function startLevel(lvl){
var tog=document.getElementById('mg-infinite-toggle');
infiniteMode=tog&&tog.classList.contains('on');
var qb=document.getElementById('mg-quit-btn');
if(qb)qb.style.display=infiniteMode?'flex':'none';
currentLevel=lvl;
matched=0;score=0;flipped=[];canFlip=false;sessionDone=false;
buildGrid(currentLevel);
updateHUD();
startAmbience();
var previewDur=CFG.PREVIEW_DURATION;
cards.forEach(function(c){c.classList.add('flipped');});
var cd=document.getElementById('mg-countdown');
var countdown=previewDur;
if(cd){cd.style.display='block';cd.textContent=String(countdown);}
setMsg('Memorize the cards!','rgba(168,85,247,0.70)');
var previewInterval=setInterval(function(){
countdown--;
if(countdown>0){
if(cd)cd.textContent=String(countdown);
} else {
clearInterval(previewInterval);
if(cd){cd.style.display='none';cd.textContent='';}
cards.forEach(function(c){c.classList.remove('flipped');});
canFlip=true;
setMsg('Find the pairs...','rgba(255,255,255,0.22)');
if(!infiniteMode)startTimer();
}
},1000);
}
function beginGame(){
var sel=document.getElementById('mg-lvl-select');
if(sel)sel.style.display='flex';
}
$(document).one(':passageend',function(){
setTimeout(function(){
initAudio();
function resizeOuter(){
var story=document.getElementById('story');
var sr=story?story.getBoundingClientRect():{top:0,left:0,width:window.innerWidth,height:window.innerHeight};
var outer=document.getElementById('mg-outer');
if(!outer)return;
outer.style.top=sr.top+'px';outer.style.left=sr.left+'px';
outer.style.width=sr.width+'px';outer.style.height=sr.height+'px';
}
resizeOuter();
window.addEventListener('resize',resizeOuter);
updateHUD();
beginGame();
},60);
});
$(document).on(':passagestart',function(){
sessionDone=true;
if(timerInterval){clearInterval(timerInterval);timerInterval=null;}
stopAmbience();
});
MG.tutNext=tutNext;
MG.startLevel=startLevel;
MG.tryStartLevel=tryStartLevel;
MG.confirmPay=confirmPay;
MG.cancelPay=cancelPay;
MG.returnCasino=returnCasino;
MG.quitGame=quitGame;
MG.showTutorial=showTutorial;
MG.toggleInfinite=toggleInfinite;
})();
<</script>><<sound "music" "music.music" true>><<if $Time !== 3>><<sound "bg" "bg.park" true>><<else>><<sound "bg" "bg.parkNight" true>><</if>><<passagebg>><<set _random = random(2)>><<if _random == 0>>
<img src="assets/img/misc/city/park/jogging/1.webp"/>
<<elseif _random == 1>>
<img src="assets/img/misc/city/park/jogging/2.webp"/>
<<elseif _random == 2>>
<img src="assets/img/misc/city/park/jogging/3.webp"/>
<</if>><</passagebg>><<InformationUiPopUp "Fitness">>
<em>+1 Fitness</em><<set $Fitness++>>
<<if $Stress <= $StressMin>><em>Stress already at minimum</em><<elseif $Stress > $StressMin>><em>-5 stress</em><<set $Stress -= 5>><</if>>
<</InformationUiPopUp>>
<div class="BottomUiBarCustom">
<<BottomButton "Move">><<link "↩️ Return">><<goto "Park">><<set $FitnessDayTime = true>><<set $Energy-->><<set $Time++>><</link>><</BottomButton>>
</div><<sound "music" "music.music" true>><<sound "bg" "bg.empty" true>><<if $Time == 3>><<goto "FinancialQuarter">><</if>><<passagebg>><img src="assets/img/misc/financialquarter/bank.webp"/><</passagebg>><<TalkRandom "Receptionist" "assets/img/character/npc/g1.jpg" "Welcome to BankUp! How can I help you?">><style>
.atmH{max-width:960px;margin:clamp(8px,1.5vw,1.2rem) auto;padding:clamp(10px,1.5vw,14px);border-radius:16px;background:rgba(20,22,28,.92);border:1px solid rgba(255,255,255,.08);box-shadow:0 10px 30px rgba(0,0,0,.35);font-family:system-ui,-apple-system,Segoe UI,Roboto,Arial,sans-serif}
.atmH__top{display:flex;align-items:center;justify-content:space-between;gap:10px;margin:0 0 10px 0}
.atmH__title{font-size:calc(clamp(12px,1.2vw,17px) + var(--font-boost,0px));letter-spacing:.08em;text-transform:uppercase;opacity:.9;padding:0 0 0 4px}
.atmH__brand{font-size:calc(clamp(11px,1.1vw,15px) + var(--font-boost,0px));opacity:.7;padding:0 4px 0 0}
.atmH__row{display:flex;gap:clamp(8px,1.2vw,12px);align-items:stretch;flex-wrap:wrap}
.atmH__screen{flex:0 0 clamp(140px,16vw,220px);border-radius:14px;padding:clamp(8px,1.2vw,12px);background:rgba(0,0,0,.35);border:1px solid rgba(255,255,255,.08);display:flex;flex-direction:column;gap:8px}
.atmH__line{display:flex;justify-content:space-between;align-items:baseline;padding:6px 0;border-bottom:1px dashed rgba(255,255,255,.10)}
.atmH__line:last-child{border-bottom:0}
.atmH__label{opacity:.75;font-size:calc(clamp(11px,1.1vw,14px) + var(--font-boost,0px))}
.atmH__value{font-size:calc(clamp(13px,1.3vw,18px) + var(--font-boost,0px));font-weight:650}
.atmH__cols{flex:1;display:grid;grid-template-columns:1fr 1fr;gap:clamp(8px,1.2vw,12px);min-width:0}
.atmH__panel{border-radius:14px;padding:clamp(8px,1.2vw,12px);background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.08);display:flex;flex-direction:column;gap:clamp(6px,1vw,10px);min-width:0}
.atmH__head{display:flex;align-items:baseline;justify-content:space-between;gap:10px;flex-wrap:wrap}
.atmH__head b{font-size:calc(clamp(12px,1.1vw,16px) + var(--font-boost,0px));opacity:.9}
.atmH__hint{font-size:calc(clamp(10px,1vw,14px) + var(--font-boost,0px));opacity:.65;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.atmH__grid{display:grid;grid-template-columns:repeat(auto-fill, minmax(min(60px,100%), 1fr));gap:clamp(4px,0.8vw,10px)}
.atmH a.link-internal,.atmH a.link-visited{display:flex;justify-content:center;align-items:center;width:100% !important;min-width:0 !important;max-width:100% !important;padding:clamp(6px,1vw,10px) 4px;border-radius:12px;text-decoration:none;user-select:none;border:1px solid rgba(255,255,255,.10);background:rgba(255,255,255,.06);color:inherit;transition:transform .05s ease,background .15s ease,border-color .15s ease,opacity .15s ease;font-weight:650;font-size:calc(clamp(10px,1vw,14px) + var(--font-boost,0px));box-sizing:border-box;overflow:hidden}
.atmH a.link-internal:hover{background:rgba(255,255,255,.10);border-color:rgba(255,255,255,.16)}
.atmH a.link-internal:active{transform:translateY(1px)}
.atmH__disabled{display:flex;justify-content:center;align-items:center;width:100% !important;min-width:0 !important;max-width:100% !important;padding:clamp(6px,1vw,10px) 4px;border-radius:12px;border:1px solid rgba(255,255,255,.06);background:rgba(255,255,255,.03);opacity:.45;font-weight:650;font-size:calc(clamp(10px,1vw,14px) + var(--font-boost,0px));box-sizing:border-box;overflow:hidden}
.atmH__msg{font-size:calc(clamp(10px,1vw,14px) + var(--font-boost,0px));opacity:.85}
.atmH__warn{color:#ff6b6b;opacity:.95}
.atmH__foot{margin-top:10px;display:flex;justify-content:space-between;gap:10px;opacity:.7;font-size:calc(clamp(10px,1vw,14px) + var(--font-boost,0px))}
@media(max-width:600px){
.atmH__cols{grid-template-columns:1fr}
.atmH__screen{flex:0 0 100%}
.atmH__row{flex-direction:column}
.atmH__hint{display:none}
}
</style><div class="atmH"><div class="atmH__top"><div class="atmH__title">ATM</div><div class="atmH__brand">SecureBank</div></div><div class="atmH__row"><div class="atmH__screen"><div class="atmH__line"><span class="atmH__label">Cash</span><span class="atmH__value">$<<print $Money>></span></div><div class="atmH__line"><span class="atmH__label">Bank</span><span class="atmH__value">$<<print $Bank>></span></div></div><div class="atmH__cols"><div class="atmH__panel"><div class="atmH__head"><b>Withdraw</b><span class="atmH__hint">Take cash from your bank</span></div><div class="atmH__grid"><<if $Bank >= 9>><<link "10">><<set $Bank -= 10, $Money += 10>><<Refresh>><</link>><<else>><span class="atmH__disabled">10</span><</if>><<if $Bank >= 49>><<link "50">><<set $Bank -= 50, $Money += 50>><<Refresh>><</link>><<else>><span class="atmH__disabled">50</span><</if>><<if $Bank >= 99>><<link "100">><<set $Bank -= 100, $Money += 100>><<Refresh>><</link>><<else>><span class="atmH__disabled">100</span><</if>><<if $Bank >= 999>><<link "1000">><<set $Bank -= 1000, $Money += 1000>><<Refresh>><</link>><<else>><span class="atmH__disabled">1000</span><</if>></div><div class="atmH__msg"><<if $Bank < 9>><span class="atmH__warn">You don't have enough money in the bank!</span><</if>></div></div><div class="atmH__panel"><div class="atmH__head"><b>Deposit</b><span class="atmH__hint">Put cash into your bank</span></div><div class="atmH__grid"><<if $Money >= 9>><<link "10">><<set $Money -= 10, $Bank += 10>><<Refresh>><</link>><<else>><span class="atmH__disabled">10</span><</if>><<if $Money >= 49>><<link "50">><<set $Money -= 50, $Bank += 50>><<Refresh>><</link>><<else>><span class="atmH__disabled">50</span><</if>><<if $Money >= 99>><<link "100">><<set $Money -= 100, $Bank += 100>><<Refresh>><</link>><<else>><span class="atmH__disabled">100</span><</if>><<if $Money >= 999>><<link "1000">><<set $Money -= 1000, $Bank += 1000>><<Refresh>><</link>><<else>><span class="atmH__disabled">1000</span><</if>></div><div class="atmH__msg"><<if $Money < 9>><span class="atmH__warn">You don't have enough cash!</span><</if>></div></div></div></div><div class="atmH__foot"></div></div>
<div class="BottomUiBarCustom"><<if $MayorStoryInfo11 == true and $MayorStoryInfo12 == false>><br><<BottomButton "Story">><<if $PsychicPower <= 0>><<link "🔒 Not enough Psychic Power">><</link>><<elseif $PsychicPower >= 1>><<link "💬 Request a Meeting">><<goto "MayorStory20">><</link>><</if>><</BottomButton>><</if>>
<<BottomButton "Move">>[[🚪 Exit|FinancialQuarter]]<</BottomButton>>
</div><<sound "music" "music.main" true>><<passagebg>><img src="assets/img/misc/dead.gif"/><</passagebg>><<InformationUiPopUp "Burnout">>
You are dead! You had a <strong>burnout</strong> due to excessive stress...
<</InformationUiPopUp>>
<div class="BottomUiBarCustom">
<<BottomButton "Story">><<Restart>><</BottomButton>>
</div><<sound "music" "music.music" true>><<passagebg>><img src="assets/img/misc/MCPC/internet/email/reading.gif"/><</passagebg>><<InformationUiPopUp "Email">><strong>Subject:</strong> What you are about to become
<strong>From:</strong> <span id="magicText" class="obf">creator@god.sky</span>
<strong>To:</strong> <<=$PlayerCS2.username>>@gmail.com
You don't know me. You never will.
But I know you. I have watched you for longer than you would be comfortable knowing. And I have chosen you, not because you are exceptional, but because you are ready. Whether you believe that or not changes nothing.
There is a force older than language, older than memory. It has no name that translates well into your tongue. Some have called it influence. Others have called it divinity. Most have simply called it impossible, and moved on with their lives.
You will not move on.
This force is already inside you. It has always been there, sealed away, waiting for something it could not name. That something is intention. Yours.
You do not need to train for years. You do not need to suffer. You only need to <u><strong>sleep</strong></u>. Each night your mind surrenders itself, the seal loosens. Each morning you wake, the power is a little more yours. It is not borrowed. It will not be taken back.
I gave you the first breath of it. The rest you will earn yourself.
<em>You will not hear from me again. You no longer need to.</em>
<</InformationUiPopUp>>
<div class="BottomUiBarCustom">
<<BottomButton "Story">>[[🤔 Strange...|StartStory2]]<</BottomButton>>
</div>
<style>
.obf {
font-family: monospace;
display: inline-block;
white-space: pre;
}
</style><<script>>
$(document).one(':passagedisplay', function () {
const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
const el = document.getElementById("magicText");
const original = el.textContent;
setInterval(()=>{
let scrambled = "";
for(let j=0;j<original.length;j++){
if(original[j] === " "){ scrambled += " "; continue; }
scrambled += chars[Math.floor(Math.random()*chars.length)];
}
el.textContent = scrambled;
}, 100);
});
<</script>><<UsePsychicPower>><<sound "music" "music.music" true>><<passagebg>><img src="assets/img/story/storystart/thinking.webp"/><</passagebg>><<InformationUiPopUp "You">><em>I stand frozen in front of the screen for a moment.</em>
<</InformationUiPopUp>>
<<TalkMC "This message… it makes no sense. A stranger talking about psychic powers, mind control, as if it were the most natural thing in the world. It sounds like a bad joke, or the rant of a fanatic.">>
<<TalkMC "Yet he knew my email address… At best, he could have guessed it, or obtained it somehow. But the strangest part is that the recipient address wasn't even displayed. As if the field itself was bugged, corrupted...">>
<<InformationUiPopUp "You">><em>It's absurd, I know. But an idea slips into my mind:</em>
<</InformationUiPopUp>>
<<TalkMC "What if it were true? I'm not being asked to do anything. No ritual, no effort. Just... be aware of it. Accept that it might already be there, waiting.">>
<<InformationUiPopUp "You">><em>I close the email. But the words stay with me. And somewhere, just beneath the surface, something stirs.</em>
<</InformationUiPopUp>>
<div class="BottomUiBarCustom">
<<BottomButton "Story">><<link "➡️ I sigh and close the email.">><<goto $MailReturnTo>><<set $MailReturnTo = "">><<set $StartStoryMail = true>><<set $StartStory = true>><</link>><</BottomButton>>
</div><<sound "music" "music.music" true>><<sound "bg" "bg.empty" true>><<passagebg>><<if $Time !== 3>><img src="assets/img/misc/neighborhood/right/bedroom.webp"/><<else>><img src="assets/img/misc/neighborhood/right/bedroomnight.webp"/><</if>><</passagebg>>
<<if $Time == 0 or $Time == 3>><<Interact $NPCRightNeighbor>><<else>><<InformationUiPopUp "Interact">>There is no one.<</InformationUiPopUp>><</if>>
<div class="BottomUiBarCustom">
<<BottomButton "Move">>[[🚪 Exit|Neighborhood]]<</BottomButton>>
</div><<sound "music" "music.music" true>><<sound "bg" "bg.empty" true>><<passagebg>><<if $Time !== 3>><img src="assets/img/misc/neighborhood/left/bedroom.webp"/><<else>><img src="assets/img/misc/neighborhood/left/bedroomnight.webp"/><</if>><</passagebg>>
<<if $Time == 0 or $Time == 3>><<Interact $NPCLeftNeighbor>><<else>><<InformationUiPopUp "Interact">>There is no one.<</InformationUiPopUp>><</if>>
<div class="BottomUiBarCustom">
<<BottomButton "Move">>[[🚪 Exit|Neighborhood]]<</BottomButton>>
</div><<sound "music" "music.music" true>><<sound "bg" "bg.empty" true>><<passagebg>><img src="assets/img/misc/city/arena/arenaempty.webp"/><</passagebg>>
<<if $Time == 1 or 2>><<Interact $NPCRightNeighbor>><<else>><<InformationUiPopUp "Interact">>There is no one.<</InformationUiPopUp>><</if>>
<div class="BottomUiBarCustom"><<if $SearchWorkMailEnd == true>><br><<BottomButton "Action">><<if $Time == 3>><<link "🔒 Arena is closed">><</link>><<else>><<if $SearchWorkMailEnd == true and $InterviewWorkArena == false>><<link "💬 Take the interview">><<goto "InterviewWork">><</link>><<elseif $InterviewWorkArena == true>>[[💼 Work|WorkArena]]<</if>><</if>><</BottomButton>><</if>>
<<BottomButton "Move">>[[🏙️ City center|City]]<</BottomButton>>
</div><<sound "music" "music.music" true>><<sound "bg" "bg.empty" true>><<passagebg>><img src="assets/img/misc/city/arena/arenaempty.webp"/><</passagebg>>
<<if $OptSkipMiniGamesOn>><<InformationUiPopUp "Work">>You put in a good shift.
<em>+$100 in Bank</em><<set $Bank += 100>>
<em>-1 Energy</em><<set $Energy -= 1>>
<</InformationUiPopUp>><<set $Time++>>
<<else>><<set $WAMScore = 0>><style>
#wam{max-width:475px;margin:0 auto;color:#fff;font-family:inherit;}
#wam .wam-topbar{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-bottom:14px;}
#wam .wam-stats{display:flex;align-items:center;gap:6px;}
#wam .wam-pill{display:inline-flex;align-items:center;gap:6px;padding:5px 12px;border-radius:999px;background:rgba(255,255,255,.05);border:1px solid rgba(255,255,255,.08);font-size:12px;font-weight:800;color:rgba(255,255,255,.80);}
#wam .wam-pill span{font-weight:950;color:rgba(255,255,255,.95);}
#wam .wam-status{font-size:13px;font-weight:900;color:rgba(255,255,255,.55);letter-spacing:.04em;}
#wam .wam-status.go{color:#e65763;}
#wam .wam-btn{all:unset;padding:7px 20px;border-radius:10px;background:rgba(230,87,99,.12);border:1px solid rgba(230,87,99,.35);color:rgba(230,87,99,.95);font-size:12px;font-weight:950;letter-spacing:.08em;cursor:pointer;transition:background .12s,border-color .12s,transform .10s;}
#wam .wam-btn:hover{background:rgba(230,87,99,.20);border-color:rgba(230,87,99,.60);transform:translateY(-1px);}
#wam .wam-btn:active{transform:scale(.96);}
#wam .wam-btn:disabled{opacity:.35;cursor:not-allowed;transform:none;}
#wam .wam-btn.tut-btn{background:rgba(255,255,255,.05);border-color:rgba(255,255,255,.15);color:rgba(255,255,255,.55);}
#wam .wam-btn.tut-btn:hover{background:rgba(255,255,255,.10);border-color:rgba(255,255,255,.30);}
#wam .wam-timebar-wrap{height:4px;border-radius:999px;background:rgba(255,255,255,.07);overflow:hidden;margin-bottom:12px;}
#wam .wam-timebar{height:100%;border-radius:999px;background:#e65763;width:100%;transition:width .1s linear;box-shadow:0 0 10px rgba(230,87,99,.40);}
#wam .wam-grid{display:grid!important;grid-template-columns:repeat(3,1fr)!important;gap:8px!important;background:rgba(0,0,0,.40);padding:10px;border-radius:14px;border:1px solid rgba(255,255,255,.07);}
.wam-cell{aspect-ratio:1;min-height:100px;background:rgba(255,255,255,.04);border:1px solid rgba(255,255,255,.08);border-radius:10px;cursor:pointer;user-select:none;transition:background .08s,border-color .08s,box-shadow .08s,transform .08s;}
.wam-cell:hover{background:rgba(255,255,255,.07);transform:scale(1.02);}
.wam-cell.active-yellow{background:rgba(218,165,32,.20);border-color:rgba(255,221,0,.55);box-shadow:0 0 18px rgba(255,221,0,.30);transform:scale(1.04);}
.wam-cell.active-orange{background:rgba(200,100,0,.22);border-color:rgba(255,149,0,.55);box-shadow:0 0 18px rgba(255,149,0,.30);transform:scale(1.04);}
.wam-cell.active-red{background:rgba(200,30,30,.22);border-color:rgba(255,60,60,.55);box-shadow:0 0 18px rgba(255,60,60,.30);transform:scale(1.04);}
#wam .wam-result{margin-top:14px;padding:14px 16px;border-radius:12px;background:rgba(230,87,99,.08);border:1px solid rgba(230,87,99,.25);display:none;text-align:center;}
#wam .wam-result-title{font-size:13px;font-weight:900;color:rgba(255,255,255,.55);letter-spacing:.10em;text-transform:uppercase;margin-bottom:4px;}
#wam .wam-result-gain{font-size:28px;font-weight:950;color:rgba(230,87,99,.95);letter-spacing:-.01em;}
#wam .wam-result-sub{font-size:11px;font-weight:700;color:rgba(255,255,255,.35);margin-top:4px;letter-spacing:.04em;}
#wam-tut-overlay{position:fixed;inset:0;z-index:9999;background:rgba(5,2,12,.96);display:none;flex-direction:column;align-items:center;justify-content:center;gap:18px;padding:32px;}
#wam-tut-overlay.visible{display:flex;}
#wam-tut-title{font-size:1.4rem;font-weight:950;color:rgba(230,87,99,.95);letter-spacing:.14em;text-transform:uppercase;text-align:center;}
#wam-tut-body{font-size:1rem;color:rgba(220,200,255,.75);text-align:center;line-height:1.8;max-width:420px;font-weight:700;}
#wam-tut-close{all:unset;padding:12px 36px;border-radius:11px;border:1px solid rgba(230,87,99,.50);background:rgba(230,87,99,.14);color:rgba(230,87,99,.95);font-weight:950;font-size:.95rem;letter-spacing:.14em;cursor:pointer;text-transform:uppercase;}
#wam-tut-close:hover{background:rgba(230,87,99,.24);}
</style>
<div id="wam-tut-overlay"><div id="wam-tut-title">How to Play</div><div id="wam-tut-body">A 9-square grid appears before you.<br><br>Click <strong>Start</strong>, a 3-second countdown begins, then the game runs for <strong>10 seconds</strong>.<br><br>Squares light up at random intervals:<br><span style="color:rgba(255,221,0,.90);">Yellow</span> = <strong>+1 pt</strong> · <span style="color:rgba(255,149,0,.90);">Orange</span> = <strong>+2 pts</strong> · <span style="color:rgba(255,100,100,.90);">Red</span> = <strong>+3 pts</strong><br><br>Click them before they disappear to score points.<br>Your final score is converted: <strong>pts × $2,5 → Bank</strong>.</div><button id="wam-tut-close">Got it</button></div><div id="wam"><div class="wam-topbar"><div class="wam-stats"><div class="wam-pill">⏱️ <span class="wam-time">10.0</span>s</div><div class="wam-pill">🎯 <span class="wam-score">0</span> pts</div></div><div class="wam-status" id="wam-status">Ready</div><button id="wam-tut-btn" class="wam-btn tut-btn">Tutorial</button><button id="wam-start" class="wam-btn">START</button></div><div class="wam-timebar-wrap"><div class="wam-timebar" id="wam-timebar"></div></div><div class="wam-grid" id="wam-grid"></div><div class="wam-result" id="wam-result"><div class="wam-result-title">Session complete</div><div class="wam-result-gain" id="wam-result-gain"></div><div class="wam-result-sub" id="wam-result-sub"></div></div></div>
<<script>>
(function(){
$(document).one(':passagedisplay',function(){
var V=State.variables;
var root=document.getElementById('wam'); if(!root) return;
var grid=document.getElementById('wam-grid');
var startBtn=document.getElementById('wam-start');
var statusEl=document.getElementById('wam-status');
var timeEl=root.querySelector('.wam-time');
var scoreEl=root.querySelector('.wam-score');
var timebar=document.getElementById('wam-timebar');
var resultBox=document.getElementById('wam-result');
var resultGain=document.getElementById('wam-result-gain');
var resultSub=document.getElementById('wam-result-sub');
var tutOverlay=document.getElementById('wam-tut-overlay');
var tutBtn=document.getElementById('wam-tut-btn');
var tutClose=document.getElementById('wam-tut-close');
tutBtn.onclick=function(){ tutOverlay.classList.add('visible'); };
tutClose.onclick=function(){ tutOverlay.classList.remove('visible'); };
var COUNTDOWN_SEC=3;
var GAME_DURATIONMS=10000;
var ACTIVE_MS=1200;
var SPAWN_INTERVAL=250;
var score=0;
var running=false;
var countdownTimer=null;
var gameTimer=null;
var spawnTimer=null;
var timeLeftMs=GAME_DURATIONMS;
grid.innerHTML='';
var cells=[];
function onCellClick(e){
if(!running) return;
var cell=e.currentTarget;
if(cell.getAttribute('data-active')!=='1') return;
var pts=parseInt(cell.getAttribute('data-points'),10)||0;
score+=pts;
updateHUD();
clearCell(cell);
cell.setAttribute('data-token',String((parseInt(cell.getAttribute('data-token'),10)||0)+1));
}
for(var i=0;i<9;i++){
var d=document.createElement('div');
d.className='wam-cell';
d.setAttribute('data-idx',String(i));
d.setAttribute('data-active','0');
d.setAttribute('data-points','0');
d.setAttribute('data-token','0');
d.addEventListener('click',onCellClick,false);
grid.appendChild(d);
cells.push(d);
}
function updateHUD(){
scoreEl.textContent=String(score);
V.WAMScore=score;
}
function setStatus(t,hot){
statusEl.textContent=t;
if(hot) statusEl.classList.add('go'); else statusEl.classList.remove('go');
}
function setTime(ms){
timeLeftMs=ms;
timeEl.textContent=(Math.max(0,ms)/1000).toFixed(1);
var pct=Math.max(0,Math.min(100,(ms/GAME_DURATIONMS)*100));
timebar.style.width=pct+'%';
timebar.style.background=pct>50?'#e65763':pct>20?'rgba(255,149,0,.90)':'rgba(255,60,60,.90)';
}
function clearCell(cell){
cell.className='wam-cell';
cell.setAttribute('data-active','0');
cell.setAttribute('data-points','0');
}
function activateCell(cell){
if(cell.getAttribute('data-active')==='1') return;
var r=Math.random();
var cls='active-yellow',pts=1;
if(r>0.6666){cls='active-red';pts=3;}
else if(r>0.3333){cls='active-orange';pts=2;}
var token=(parseInt(cell.getAttribute('data-token'),10)||0)+1;
cell.setAttribute('data-token',String(token));
cell.className='wam-cell '+cls;
cell.setAttribute('data-active','1');
cell.setAttribute('data-points',String(pts));
setTimeout(function(){
if(cell.getAttribute('data-token')!==String(token)) return;
clearCell(cell);
},ACTIVE_MS);
}
function spawnOnce(){
var inactive=[];
for(var k=0;k<cells.length;k++){
if(cells[k].getAttribute('data-active')!=='1') inactive.push(cells[k]);
}
if(inactive.length===0) return;
activateCell(inactive[Math.floor(Math.random()*inactive.length)]);
}
function endGame(){
running=false;
if(spawnTimer){clearInterval(spawnTimer);spawnTimer=null;}
if(gameTimer){clearInterval(gameTimer);gameTimer=null;}
for(var k=0;k<cells.length;k++) clearCell(cells[k]);
var gain=score*2.5;
V.Bank=(V.Bank||0)+gain;
V.Energy=(V.Energy||0)-1;
V.Time=(V.Time||0)+1;
setStatus('Finished!',false);
setTime(0);
resultGain.textContent='+'+gain+' $';
resultSub.textContent=score+' pts × 2,5 = '+gain+' added to Bank';
resultBox.style.display='block';
}
function startGame(){
running=true;
score=0;
resultBox.style.display='none';
updateHUD();
setStatus('GO!',true);
setTime(GAME_DURATIONMS);
var t0=Date.now();
spawnTimer=setInterval(spawnOnce,SPAWN_INTERVAL);
gameTimer=setInterval(function(){
var elapsed=Date.now()-t0;
var remain=GAME_DURATIONMS-elapsed;
setTime(remain>0?remain:0);
if(remain<=0){clearInterval(gameTimer);endGame();}
},100);
}
function startCountdown(){
startBtn.disabled=true;
startBtn.textContent='…';
resultBox.style.display='none';
var n=COUNTDOWN_SEC;
setStatus('Ready?',false);
setTime(GAME_DURATIONMS);
updateHUD();
countdownTimer=setInterval(function(){
setStatus('Starting in '+n+'…',false);
n--;
if(n<0){clearInterval(countdownTimer);startGame();}
},1000);
}
startBtn.onclick=startCountdown;
setStatus('Ready',false);
setTime(GAME_DURATIONMS);
updateHUD();
});
})();
<</script>>
<</if>>
<div class="BottomUiBarCustom">
<<BottomButton "Move">>[[↩️ Return|Arena]]<</BottomButton>>
</div><<sound "music" "music.music" true>><<passagebg>><img src="assets/img/story/searchwork/search.webp"/><</passagebg>><<InformationUiPopUp "Internet">>After long hours of searching and making inquiries, I finally come across a job listing that catches my attention.
A janitor position is offered at the <strong>Arena</strong>, not far from the city center.
What makes this offer even more interesting is the flexibility it provides: there are no fixed working hours. I’m free to come work whenever I’m available, and every hour worked is properly paid.
<</InformationUiPopUp>>
<div class="BottomUiBarCustom">
<<BottomButton "Story">>[[💼 Apply for the offer|SearchWork2]]<</BottomButton>>
</div><<sound "music" "music.music" true>><<passagebg>><img src="assets/img/story/searchwork/apply.webp"/><</passagebg>><<InformationUiPopUp "Internet">>After filling out the form and sending my application for the janitor position at the Arena.
<</InformationUiPopUp>>
<<TalkMC "All that’s left is to wait and keep an eye on my inbox, the reply should arrive tomorrow...">>
<div class="BottomUiBarCustom">
<<BottomButton "Story">><<link "➡️ Leave the page">><<goto "Internet">><<set $SearchWork = true>><<set $SearchWorkDayInt = $Day>><</link>><</BottomButton>>
</div><<sound "music" "music.music" true>><<passagebg>><img src="assets/img/misc/MCPC/internet/email/reading.gif"/><</passagebg>><<InformationUiPopUp "Email">><em>A new message appears in your inbox.</em>
I open the email, my profile has been selected, and I’m invited to attend an interview for the janitor position at the <strong>Arena</strong>.
<em>The email specifies that the Arena will be open between morning and afternoon, which gives me some flexibility to go there.</em>
<</InformationUiPopUp>>
<div class="BottomUiBarCustom">
<<BottomButton "Story">><<link "➡️ I need to go to the Arena">><<goto $MailReturnTo>><<set $MailReturnTo = "">><<set $SearchWorkMailEnd = true>><</link>><</BottomButton>>
</div><<sound "music" "music.music" true>><<sound "bg" "bg.empty" true>><<passagebg>><img src="assets/img/story/searchwork/interviewwork.webp"/><</passagebg>><<TalkMC "Hello, I’m here for the janitor job interview.">>
<<TalkRandom "Recruiter" "assets/img/character/npc/b4.jpg" "Hello, have a seat. We’ll start with a few simple questions.">>
<<TalkMC "Of course, I’m ready.">>
<<TalkRandom "Recruiter" "assets/img/character/npc/b4.jpg" "Very well… Tell me, have you already worked in cleaning or maintenance before?">>
<<TalkMC "Yes, I’ve had a few similar experiences. I’m serious, organized, and I adapt quickly.">>
<<InformationUiPopUp "One hour later">><em>After several more questions...</em>
<</InformationUiPopUp>>
<<TalkRandom "Recruiter" "assets/img/character/npc/b4.jpg" "Perfect. Your profile matches what we’re looking for. You’re hired, welcome aboard.">>
<div class="BottomUiBarCustom">
<<BottomButton "Story">><<link "➡️ Exit">><<goto "Arena">><<set $InterviewWorkArena = true>><</link>><</BottomButton>>
</div><<sound "music" "music.music" true>><<passagebg>><img src="assets/img/misc/city/mall/gym/reception.webp"/><</passagebg>><<TalkMC "Hello! I was wondering if I could get some information about your gym.">>
<<TalkNPC $NPCBossGym "Hello, welcome! Yes of course, what would you like to know?">>
<<TalkMC "First, is the gym open every day? And most importantly, how much does a membership cost?">>
<<TalkNPC $NPCBossGym "The gym is open 7 days a week, from morning until the afternoon. As for the membership, it is <b>$60 for 30 days</b>.">>
<<TalkMC "Alright, so $60 for a month. Does that also include group classes, or only access to the machines?">>
<<TalkNPC $NPCBossGym "The price includes full access to the gym, machines and free weights. Group classes are also included in the membership, you just need to reserve your spot in advance.">>
<<TalkMC "Great! And are there any additional registration fees, or just the $60?">>
<<TalkNPC $NPCBossGym "No, no registration fees. You only pay the $60 for your 10 days of access.">>
<<TalkMC "Perfect. Thanks for the info, I’ll think about it.">>
<<TalkNPC $NPCBossGym "My pleasure! If you have any other questions, don’t hesitate.">>
<div class="BottomUiBarCustom">
<<BottomButton "Action">><<link "💳 Get a membership">><<goto "Gym">><<set $GymSub = true>><<set $GymSubDayInt = $Day>><<set $Bank -= 60>><</link>> | $60 / 10 Days<</BottomButton>>
<<BottomButton "Move">>[[❌ Don't get a membership|Gym]]<</BottomButton>>
</div><<sound "music" "music.music" true>><<passagebg>><<set _random = random(2)>><<if _random == 0>>
<img src="assets/img/misc/city/mall/gym/workout1.webp"/>
<<elseif _random == 1>>
<img src="assets/img/misc/city/mall/gym/workout2.webp"/>
<<elseif _random == 2>>
<img src="assets/img/misc/city/mall/gym/workout3.webp"/>
<</if>><</passagebg>><<InformationUiPopUp "Fitness">>
<em>+2 Fitness</em><<set $Fitness += 2>>
<<if $Stress <= $StressMin>><em>Stress already at minimum</em><<elseif $Stress > $StressMin>><em>-5 stress</em><<set $Stress -= 5>><</if>>
<</InformationUiPopUp>>
<div class="BottomUiBarCustom">
<<BottomButton "Move">><<link "↩️ Return">><<goto "Gym">><<set $FitnessDayTime = true>><<set $Energy-->><<set $Time++>><</link>><</BottomButton>>
</div><<sound "music" "music.music" true>><<passagebg>><img src="assets/img/misc/DoorClosed.webp"/><</passagebg>><<InformationUiPopUp "*Toc* *Toc*">>
<em>No one answers...</em>
<</InformationUiPopUp>>
<div class="BottomUiBarCustom">
<<BottomButton "Move">><<return>><</BottomButton>>
</div><<sound "music" "music.music" true>><<bgpersist true>><<if $NPCLandlady.met == false>><<FirstContact $NPCLandlady true>><<else>><<if $Time == 3 and $NPCLandlady.lvl >= 2>><<InteractMenu $NPCLandlady>><<elseif $Time == 3>><<Sleeping $NPCLandlady>><<else>><<InteractMenu $NPCLandlady>><</if>><</if>>
<div class="BottomUiBarCustom">
<<BottomButton "Move">><<ReturnTo>><</BottomButton>>
</div><<sound "music" "music.music" true>><<sound "sfx" "sfx.shower" true>><<passagebg>><img src="assets/img/misc/home/bathroom/bathroom.webp"/><</passagebg>><<Shower $NPCHousemateFemale>>
<div class="BottomUiBarCustom">
<<BottomButton "Move">>[[↩️ Return|Bathroom]]<</BottomButton>>
</div><<sound "music" "music.music" true>><<sound "sfx" "sfx.shower" true>><<passagebg>><img src="assets/img/misc/home/bathroom/bathroom.webp"/><</passagebg>><<Shower $NPCLandlady>>
<div class="BottomUiBarCustom">
<<BottomButton "Move">>[[↩️ Return|Bathroom]]<</BottomButton>>
</div><<sound "music" "music.music" true>><<bgpersist true>><<if $NPCHousemateFemale.met == false>><<FirstContact $NPCHousemateFemale true>><<else>><<if $NPCHousemateFemale.talklvl <= 0 and $Time == 0>><<goto "Talk.HousemateFemale">><</if>><<if $Time == 3 and $NPCHousemateFemale.lvl >= 2>><<InteractMenu $NPCHousemateFemale>><<elseif $Time == 3>><<Sleeping $NPCHousemateFemale>><<else>><<InteractMenu $NPCHousemateFemale>><</if>><</if>>
<div class="BottomUiBarCustom">
<<BottomButton "Move">><<ReturnTo>><</BottomButton>>
</div><<sound "music" "music.music" true>><<bgpersist true>>/*<<if $NPCHousemateMale.met == false>><<FirstContact $NPCHousemateMale true>><<else>><<InteractMenu $NPCHousemateMale>><</if>>*/<<WIP>>
<div class="BottomUiBarCustom">
<<BottomButton "Move">><<ReturnTo>><</BottomButton>>
</div><<sound "music" "music.music" true>><<bgpersist true>>/*<<if $NPCLandlord.met == false>><<FirstContact $NPCLandlord true>><<else>><<InteractMenu $NPCLandlord>><</if>>*/<<WIP>>
<div class="BottomUiBarCustom"><<if $SedativesGlassWater == true and $Time == 3 and $LandladyChapter6Story4Played == false>><br><<BottomButton "Action">><<link "🥛 Give her the Glass of Water">><<set $ActiveNPC = $NPCLandlord>><<goto "LandladyChapter6Story4">><</link>><</BottomButton>><</if>>
<<BottomButton "Move">><<ReturnTo>><</BottomButton>>
</div><<sound "music" "music.music" true>><<bgpersist true>>/*<<if $NPCOnlineFriend.met == false>><<FirstContact $NPCOnlineFriend false>><<else>>Custom for Online porn<</if>>*/<<WIP>>
<div class="BottomUiBarCustom">
<<BottomButton "Move">><<ReturnTo>><</BottomButton>>
</div><<sound "music" "music.music" true>><<bgpersist true>>/*<<if $NPCLeftNeighbor.met == false>><<FirstContact $NPCLeftNeighbor false>><<else>><<if $Time == 3 and $NPCLeftNeighbor.lvl >= 2>><<InteractMenu $NPCLeftNeighbor>><<elseif $Time == 3>><<Sleeping $NPCLeftNeighbor>><<else>><<InteractMenu $NPCLeftNeighbor>><</if>><</if>>*/<<WIP>>
<div class="BottomUiBarCustom">
<<BottomButton "Move">><<ReturnTo>><</BottomButton>>
</div><<sound "music" "music.music" true>><<bgpersist true>>/*<<if $NPCRightNeighbor.met == false>><<FirstContact $NPCRightNeighbor false>><<else>><<InteractMenu $NPCRightNeighbor>><</if>>*/<<WIP>>
<div class="BottomUiBarCustom">
<<BottomButton "Move">><<ReturnTo>><</BottomButton>>
</div><<sound "music" "music.music" true>><<bgpersist true>><<if $NPCBestFriend.met == false>><<FirstContact $NPCBestFriend false>><<else>><<if $Time == 3 and $NPCBestFriend.lvl >= 2>><<InteractMenu $NPCBestFriend>><<elseif $Time == 3>><<Sleeping $NPCBestFriend>><<else>><<InteractMenu $NPCBestFriend>><</if>><</if>>
<div class="BottomUiBarCustom">
<<BottomButton "Move">><<ReturnTo>><</BottomButton>>
</div><<sound "music" "music.music" true>><<bgpersist true>><<if $NPCMate1.met == false>><<FirstContact $NPCMate1 false>><<else>><<if $Time == 3 and $NPCMate1.lvl >= 2>><<InteractMenu $NPCMate1>><<elseif $Time == 3>><<Sleeping $NPCMate1>><<else>><<InteractMenu $NPCMate1>><</if>><</if>>
<div class="BottomUiBarCustom">
<<BottomButton "Move">><<ReturnTo>><</BottomButton>>
</div><<sound "music" "music.music" true>><<bgpersist true>><<if $NPCMate2.met == false>><<FirstContact $NPCMate2 false>><<else>><<if $Time == 3 and $NPCMate2.lvl >= 2>><<InteractMenu $NPCMate2>><<elseif $Time == 3>><<Sleeping $NPCMate2>><<else>><<InteractMenu $NPCMate2>><</if>><</if>>
<div class="BottomUiBarCustom">
<<BottomButton "Move">><<ReturnTo>><</BottomButton>>
</div><<sound "music" "music.music" true>><<bgpersist true>><<if $NPCMate3.met == false>><<FirstContact $NPCMate3 false>><<else>><<if $Time == 3 and $NPCMate3.lvl >= 2>><<InteractMenu $NPCMate3>><<elseif $Time == 3>><<Sleeping $NPCMate3>><<else>><<InteractMenu $NPCMate3>><</if>><</if>>
<div class="BottomUiBarCustom">
<<BottomButton "Move">><<ReturnTo>><</BottomButton>>
</div><<sound "music" "music.music" true>><<bgpersist true>>/*<<if $NPCTeachSport.met == false>><<FirstContact $NPCTeachSport false>><<else>><<if $Time == 3 and $NPCTeachSport.lvl >= 2>><<InteractMenu $NPCTeachSport>><<elseif $Time == 3>><<Sleeping $NPCTeachSport>><<else>><<InteractMenu $NPCTeachSport>><</if>><</if>>*/<<WIP>>
<div class="BottomUiBarCustom">
<<BottomButton "Move">><<ReturnTo>><</BottomButton>>
</div><<sound "music" "music.music" true>><<bgpersist true>>/*<<if $NPCTeachTech.met == false>><<FirstContact $NPCTeachTech false>><<else>><<InteractMenu $NPCTeachTech>><</if>>*/<<WIP>>
<div class="BottomUiBarCustom">
<<BottomButton "Move">><<ReturnTo>><</BottomButton>>
</div><<sound "music" "music.music" true>><<bgpersist true>>/*<<if $NPCTeachLang.met == false>><<FirstContact $NPCTeachLang false>><<else>><<InteractMenu $NPCTeachLang>><</if>>*/<<WIP>>
<div class="BottomUiBarCustom">
<<BottomButton "Move">><<ReturnTo>><</BottomButton>>
</div><<sound "music" "music.music" true>><<bgpersist true>>/*<<if $NPCBossGym.met == false>><<FirstContact $NPCBossGym false>><<else>><<if $Time == 3 and $NPCBossGym.lvl >= 2>><<InteractMenu $NPCBossGym>><<elseif $Time == 3>><<Sleeping $NPCBossGym>><<else>><<InteractMenu $NPCBossGym>><</if>><</if>>*/<<WIP>>
<div class="BottomUiBarCustom">
<<BottomButton "Move">><<ReturnTo>><</BottomButton>>
</div><<sound "music" "music.music" true>><<bgpersist true>>/*<<if $NPCBossMarket.met == false>><<FirstContact $NPCBossMarket false>><<else>><<if $Time == 3 and $NPCBossMarket.lvl >= 2>><<InteractMenu $NPCBossMarket>><<elseif $Time == 3>><<Sleeping $NPCBossMarket>><<else>><<InteractMenu $NPCBossMarket>><</if>><</if>>*/<<WIP>>
<div class="BottomUiBarCustom">
<<BottomButton "Move">><<ReturnTo>><</BottomButton>>
</div><<sound "music" "music.music" true>><<bgpersist true>><<if $NPCMayor.met == false>><<FirstContact $NPCMayor false>><<else>><<if $Time == 3 and $NPCMayor.lvl >= 2>><<InteractMenu $NPCMayor>><<elseif $Time == 3>><<Sleeping $NPCMayor>><<else>><<InteractMenu $NPCMayor>><</if>><</if>>
<div class="BottomUiBarCustom">
<<BottomButton "Move">><<ReturnTo>><</BottomButton>>
</div><<sound "music" "music.music" true>><<bgpersist true>>/*<<if $NPCHomeless.met == false>><<FirstContact $NPCHomeless false>><<else>><<InteractMenu $NPCHomeless>><</if>>*/<<WIP>>
<div class="BottomUiBarCustom">
<<BottomButton "Move">><<ReturnTo>><</BottomButton>>
</div><<sound "music" "music.music" true>><<bgpersist true>>/*<<if $NPCSexShop.met == false>><<FirstContact $NPCSexShop false>><<else>><<if $Time == 0 and $NPCSexShop.lvl >= 2>><<InteractMenu $NPCSexShop>><<elseif $Time == 0>><<Sleeping $NPCSexShop>><<else>><<InteractMenu $NPCSexShop>><</if>><</if>>*/<<WIP>>
<div class="BottomUiBarCustom">
<<BottomButton "Move">><<ReturnTo>><</BottomButton>>
</div><<sound "music" "music.music" true>><<bgpersist true>><<if $NPCPrincipal.met == false>><<FirstContact $NPCPrincipal false>><<else>><<if $Time == 3 and $NPCPrincipal.lvl >= 2>><<InteractMenu $NPCPrincipal>><<elseif $Time == 3>><<Sleeping $NPCPrincipal>><<else>><<InteractMenu $NPCPrincipal>><</if>><</if>>
<div class="BottomUiBarCustom">
<<BottomButton "Move">><<ReturnTo>><</BottomButton>>
</div><<sound "music" "music.music" true>><<set _raw = $ActiveNPC>><<if !_raw or _raw.id is undefined>>Invalid NPC.<<else>><<set _id = String(_raw.id)>><<set _key = "NPC" + _id>><<run State.temporary.npcObj = State.variables[State.temporary.key] || State.variables[_key]>><<set _npc = _npcObj>><<set _gotoNpc = _npc.id + ".interact">>
/* ====================================================
*
* ----------------------------------- CHAPTER 1 -----------------------------------------
*
*/ ====================================================
<<if _npc.talklvl == 0>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><</if>>
<<passagebg>><<sound "bg" "bg.empty" true>><img src="assets/img/misc/home/mcbedroom.webp"><</passagebg>>
<<InformationUiPopUp>>I'm in my bed, hands under the covers, jerking off, not hearing the footsteps in the hallway. I don't have time to react before the door opens.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/0/01.mp4"/>
<<TalkNPC _npc "What... what are you doing?">>
<<TalkMC "I... nothing.">>
<<TalkNPC _npc "Yeah, sure.">>
<<InformationUiPopUp>>She sets a pack of tissues on the nightstand with a sharp thud.
<</InformationUiPopUp>>
<<TalkNPC _npc "Come on, get up. Stop jerking off, you've got a whole day ahead of you!">>
<<TalkMC "I was about to get up.">>
<<TalkNPC _npc "Right. Keep telling yourself that.">>
<<InformationUiPopUp>>She leaves, pulling the door halfway behind her. I finally get up and head to the kitchen.
<</InformationUiPopUp>>
<<revealtext "wakeup">><<passagebg>><img src="assets/img/misc/home/kitchen.webp"/><</passagebg>><<InformationUiPopUp>>She's already at the island, a jar in her hands, trying to open it. Even back when she came into my room, the way she talked, her gestures, and now this, everything points to her being annoyed about something.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/0/02.mp4"/>
<<TalkMC "Did you sleep badly?">>
<<TalkNPC _npc "I'm fine.">>
<<TalkMC "Really?">>
<<TalkNPC _npc "I told you I'm fine.">>
<<InformationUiPopUp>>She pulls at the lid without success, jaw slightly tight. That gives me an idea.
<</InformationUiPopUp>><</revealtext>>
<<revealtext "chapter1">><<InformationUiPopUp "Psychic Power" #7aa2ff>>You decide to use your power on <<=_npc.name>>.
<em>-1 Psychic Power</em><</InformationUiPopUp>>
<<TalkMC "Listen to me.">>
<<TalkMC "When you're next to me, you feel good. Lighter, less stressed. My presence relaxes you naturally.">>
<<InformationUiPopUp>>I step closer and take the jar. The lid gives way without effort. She takes it back, and something in her expression shifts, just a slight release. Her hand lingers for a moment on my forearm, feeling my muscles.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/0/03.mp4"/>
<<TalkNPC _npc "Thanks.">>
<<TalkMC "No problem.">>
<<TalkNPC _npc "At least you have arms that are good for something.">>
<<TalkMC "I'll take that as a compliment.">>
<<InformationUiPopUp>>She spreads the paste on a slice of bread, her movements calmer than before. The conversation picks back up naturally.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/0/04.mp4"/>
<<TalkNPC _npc "Do you have plans today?">>
<<TalkMC "A few things. You?">>
<<TalkNPC _npc "Big day ahead. But right now, weirdly, I feel a bit better.">>
<<TalkMC "Must be my presence.">>
<<InformationUiPopUp>>She laughs lightly, a breath through her nose.
<</InformationUiPopUp>>
<<TalkNPC _npc "Yeah, sure.">>
<<InformationUiPopUp>>We keep talking for a while before going our separate ways.
<</InformationUiPopUp>><</revealtext>>
/* ====================================================
*
* ----------------------------------- CHAPTER 2 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 1>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><</if>>
<<passagebg>><<sound "bg" "bg.empty" true>><img src="assets/img/misc/home/livingroom.webp"/><</passagebg>>
<<InformationUiPopUp>>I'm in the living room when I hear the front door open.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/1/01.mp4"/>
<<InformationUiPopUp>>She sets her bags down at the entrance and heads to the living room. When she sees me, she stops.
<</InformationUiPopUp>>
<<TalkNPC _npc "Oh. I thought the house was empty.">>
<<TalkMC "Disappointed?">>
<<TalkNPC _npc "No, it's just... I wasn't expecting to see you here.">>
<<InformationUiPopUp>>She settles onto the couch, and something in her attitude shifts almost immediately. She's slightly more upbeat, more relaxed. The effect of the power, still there.
<</InformationUiPopUp>>
<<TalkMC "Did you have a good day?">>
<<TalkNPC _npc "Yes, I went out shopping.">>
<<TalkMC "Find anything good?">>
<<TalkNPC _npc "Some clothes. I needed to refresh a few things.">>
<<TalkMC "What kind of things?">>
<<TalkNPC _npc "Some outfits, a pajama set, that kind of thing.">>
<<InformationUiPopUp>>She gets up and grabs one of her bags.
<</InformationUiPopUp>>
<<TalkNPC _npc "I'm going to go get changed.">>
<<InformationUiPopUp>>That's exactly when an idea comes to me.
<</InformationUiPopUp>>
<<revealtext "chapter2">><<InformationUiPopUp "Psychic Power" #7aa2ff>>You decide to use your power on <<=_npc.name>>.
<em>-1 Psychic Power</em><</InformationUiPopUp>>
<<TalkMC "Listen to me.">>
<<TalkMC "You're going to get changed here, in the living room. Being naked in front of me won't bother you, you'll find it natural and normal.">>
<<TalkNPC _npc "...">>
<<InformationUiPopUp>>She stops, giving the order time to settle. Then she looks at the bag in her hands, the living room around her, and gives a slight shrug.
<</InformationUiPopUp>>
<<TalkNPC _npc "Might as well change here, it's much more practical.">>
<<InformationUiPopUp>>She rummages through her bag, pulls out the pajamas and underwear, and starts undressing without another thought, as if she were changing in her own room.
<</InformationUiPopUp>>
<<InformationUiPopUp>>She takes off her clothes, finds herself naked, and slips on a black lace thong.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/1/02.mp4"/>
<<InformationUiPopUp>>She then puts on a matching bra, still without the slightest hesitation.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/1/03.mp4"/>
<<InformationUiPopUp>>She finishes by pulling on the top and then the pants of her pink satin pajama set.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/1/04.mp4"/>
<<TalkNPC _npc "Hhaa...">>
<<TalkNPC _npc "There we go, that's much better.">>
<<TalkMC "Not bad.">>
<<TalkNPC _npc "The pajamas? Yeah, they're really comfortable.">>
<<InformationUiPopUp>>She picks up her old clothes and heads back to her room, perfectly relaxed, as if what had just happened was the most normal thing in the world.
<</InformationUiPopUp>><</revealtext>>
/* ====================================================
*
* ----------------------------------- CHAPTER 3 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 2>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><</if>>
<<passagebg>><<sound "bg" "bg.empty" true>><img src="assets/img/misc/home/entrance.webp"/><</passagebg>>
<<InformationUiPopUp>>I'm in the house when I hear the doorbell ring. I make my way to the door and open it. She's there, <<=_npc.name>>, arms loaded with bags.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/2/01.mp4"/>
<<TalkMC "Ringing the bell now?">>
<<TalkNPC _npc "I forgot my keys inside.">>
<<TalkMC "Ah.">>
<<TalkNPC _npc "Yeah, ah.">>
<<InformationUiPopUp>>She comes in, slightly annoyed. But as soon as she steps through the door and finds herself next to me, her attitude shifts, her expression softens.
<</InformationUiPopUp>>
<<TalkMC "You've got bags again...">>
<<TalkNPC _npc "I went shopping.">>
<<TalkMC "Again?">>
<<TalkNPC _npc "At least look at what I found.">>
<<InformationUiPopUp>>She looks down, I follow the movement. She shows me her feet, her new heels.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/2/02.mp4"/>
<<TalkNPC _npc "Pretty, right?">>
<<TalkMC "Not bad.">>
<<InformationUiPopUp>>She then starts turning around, showing off her form-fitting dress.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/2/03.mp4"/>
<<TalkNPC _npc "And the dress? I bought that today too.">>
<<TalkMC "It suits you.">>
<<TalkNPC _npc "Thanks. I've got other stuff in the bags too.">>
<<TalkMC "Show me. You can get changed in the living room, like usual.">>
<<TalkNPC _npc "Good idea.">>
<<revealtext "golivingroom">><<passagebg>><img src="assets/img/misc/home/livingroom.webp"/><</passagebg>><<InformationUiPopUp>>She picks up her bags and follows me to the living room. I settle into the armchair.
<</InformationUiPopUp>>
<<InformationUiPopUp>>She stands in front of me and starts talking about what she found, her hands sliding over her dress, pulling the fabric up slightly over her thighs, letting her underwear show.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/2/04.mp4"/>
<<TalkNPC _npc "I also found some underwear, wait, I'm going to put them on, you'll see.">>
<<InformationUiPopUp>>She keeps lifting her dress then takes it off completely, ending up in light green underwear, smiling.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/2/05.mp4"/>
<<InformationUiPopUp>>She pulls her new underwear out of a bag and holds them up for me to see.
<</InformationUiPopUp>>
<<TalkNPC _npc "Cute, right?">>
<<TalkMC "Very.">>
<<InformationUiPopUp>>I watch her swap out her underwear for the new black lace ones. And that's when I can't hold back anymore.
<</InformationUiPopUp>><</revealtext>>
<<revealtext "chapter3">><<InformationUiPopUp "Psychic Power" #7aa2ff>>You decide to use your power on <<=_npc.name>>.
<em>-1 Psychic Power</em><</InformationUiPopUp>>
<<TalkMC "Listen to me.">>
<<TalkMC "You're so comfortable and happy being with me that you're going to want to jerk me off. You feel like doing it, it seems completely natural to you right now.">>
<<TalkNPC _npc "...">>
<<InformationUiPopUp>>A few seconds. Then she sets her things down on the couch, moves closer and kneels in front of the armchair.
<</InformationUiPopUp>>
<<TalkNPC _npc "I feel like having a little fun with you.">>
<<InformationUiPopUp>>She pulls my trousers down and tosses them to the side without hesitating. She takes my cock in both hands, her head tilted right behind it, eyes on mine.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/2/06.mp4"/>
<<TalkNPC _npc "You like that?">>
<<TalkMC "Incredible.">>
<<InformationUiPopUp>>She starts moving her hand, slowly at first, then picks up the pace quickly.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/2/07.mp4"/>
<<TalkNPC _npc "Is that good?">>
<<TalkMC "Great, keep going.">>
<<InformationUiPopUp>>She speeds up again, eyes on mine, steady, focused.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/2/08.mp4"/>
<<InformationUiPopUp>>She keeps going without stopping until I finish. Once it's done, she gets up calmly, wipes her hands, picks her things back up from the couch and carries on sorting through her purchases as if nothing had just happened.
<</InformationUiPopUp>><</revealtext>>
/* ====================================================
*
* ----------------------------------- CHAPTER 4 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 3>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><</if>>
<<passagebg>><<sound "bg" "bg.empty" true>><img src="assets/img/misc/home/livingroom.webp"/><</passagebg>>
<<InformationUiPopUp>>I'm in the living room when I hear the front door. She comes into the living room with bags, again.
<</InformationUiPopUp>>
<<TalkMC "I feel like I always see you with shopping bags.">>
<<TalkNPC _npc "Seriously? You sound just like my husband.">>
<<TalkMC "Is that all?">>
<<TalkNPC _npc "You know what, fine, I'll just show you what I bought, you can give me your opinion.">>
<<InformationUiPopUp>>She sets her bags down and starts undressing in front of me, without any shame, with a completely natural ease. Once naked, she grabs her things from the bag and settles onto the couch across from me.
<</InformationUiPopUp>>
<<InformationUiPopUp>>She pulls her red lace thong halfway up, then stands and comes closer so I can see better.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/3/01.mp4"/>
<<InformationUiPopUp>>I put a hand on her ass, she laughs and carries on fastening her matching bra.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/3/02.mp4"/>
<<TalkNPC _npc "So?">>
<<TalkMC "Not bad at all.">>
<<InformationUiPopUp>>She heads back to the couch, bends forward to take off the red thong, then sits down to finish pulling it off, legs spread wide.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/3/03.mp4"/>
<<InformationUiPopUp>>She stands back up naked, takes the black panther underwear set from the bag and walks toward me, setting part of it on the edge of the seat, keeping just the thong in her hand.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/3/04.mp4"/>
<<InformationUiPopUp>>She puts on the black panther thong standing in front of me, giving me a full view of her body.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/3/05.mp4"/>
<<TalkNPC _npc "Do you like this one more?">>
<<TalkMC "Definitely.">>
<<InformationUiPopUp>>She turns around, presenting her ass to me. I slap and grope her ass, she laughs, then turns back to face me, tits bare.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/3/06.mp4"/>
<<InformationUiPopUp>>She fastens her black panther lace bra in front of me. Once it's on, I give a thumbs up to validate the outfit.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/3/07.mp4"/>
<<TalkNPC _npc "I should have gone shopping with you a long time ago.">>
<<TalkMC "Clearly.">>
<<InformationUiPopUp>>She sits sideways on my lap and pulls on a black thigh-high stocking, taking her time.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/3/08.mp4"/>
<<InformationUiPopUp>>She stands back up, facing me, and finishes straightening out her thigh-highs properly. I watch her.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/3/09.mp4"/>
<<InformationUiPopUp>>She turns around and slowly rubs her ass against my cock through my trousers, deliberately, in a way designed to turn me on. It's too much.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/3/10.mp4"/>
<<InformationUiPopUp>>I can't hold back anymore.
<</InformationUiPopUp>>
<<revealtext "chapter4">><<InformationUiPopUp "Psychic Power" #7aa2ff>>You decide to use your power on <<=_npc.name>>.
<em>-1 Psychic Power</em><</InformationUiPopUp>>
<<TalkMC "Listen to me.">>
<<TalkMC "You're so turned on being with me that you have an irresistible urge to suck me off. You need it, it feels completely normal and natural to you now.">>
<<TalkNPC _npc "...">>
<<InformationUiPopUp>>She stops, then slowly turns around and slides between my legs, kneeling in front of me.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/3/11.mp4"/>
<<TalkNPC _npc "<em>Glrk... mmh... ghlk...</em>">>
<<TalkMC "Keep going.">>
<video src="assets/img/story/character/landlady/3/12.mp4"/>
<<TalkNPC _npc "<em>Mmh... glrk...</em>">>
<<InformationUiPopUp>>She moves down to my balls, licks them slowly, then comes back up, tongue out. I tap my cock against her tongue and her face, she sticks her tongue out, waiting.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/3/13.mp4"/>
<<InformationUiPopUp>>She takes off her bra. Once her tits are bare, I take them in my hands, she moves closer so I keep going.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/3/14.mp4"/>
<<TalkNPC _npc "<em>Mmh...</em>">>
<<InformationUiPopUp>>She presses her tits around my cock and starts making slow back and forth movements.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/3/15.mp4"/>
<<InformationUiPopUp>>I end up coming. She doesn't pull back, letting me shoot all my cum onto her chest and tits, then gets up, cleans herself off and gets dressed calmly, before we both go back to our own things, as if it were the most natural thing in the world.
<</InformationUiPopUp>><</revealtext>>
/* ====================================================
*
* ----------------------------------- CHAPTER 5 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 4>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><</if>>
<<passagebg>><<sound "bg" "bg.empty" true>><img src="assets/img/misc/home/livingroom.webp"/><</passagebg>>
<<InformationUiPopUp>>I'm in the living room, slumped in the armchair, the TV on in front of a series. My phone vibrates in my pocket. A notification from the surveillance app.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/4/01.mp4"/>
<<InformationUiPopUp>>The bathroom camera. I unlock it and watch the live feed.
<</InformationUiPopUp>>
<<TalkMC "Ooh.. I like that.">>
<<InformationUiPopUp>>She's in front of the mirror in light green underwear, looking at herself, getting ready for her bath.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/4/02.mp4"/>
<<InformationUiPopUp>>She takes off her bra, her tits free in the bathroom light.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/4/03.mp4"/>
<<InformationUiPopUp>>Then her underwear, leaving herself completely naked.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/4/04.mp4"/>
<<InformationUiPopUp>>She steps into the bathtub and gets on her knees in the warm water.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/4/05.mp4"/>
<<InformationUiPopUp>>She lathers up, slowly rubbing her tits, then bends forward to reach her ass.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/4/06.mp4"/>
<<InformationUiPopUp>>I zoom in on different parts of her body as she washes.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/4/07.mp4"/>
<video src="assets/img/story/character/landlady/4/08.mp4"/>
<<InformationUiPopUp>>I watch for a few more seconds. Then I put my phone away and get up, heading toward the bathroom.
<</InformationUiPopUp>>
<<revealtext "enterbathroom">><<passagebg>><img src="assets/img/misc/home/bathroom/bathroom.webp"/><</passagebg>><<InformationUiPopUp>>I move quietly, push the door open slightly and slip inside. I hide behind the wall, watching from there.
<</InformationUiPopUp>>
<<InformationUiPopUp>>Then I remember the second order I gave her. That she couldn't care less about being naked in front of me. So I step out from my hiding spot and walk into the room. She looks up when she hears my footsteps, sees me, and smiles, happy to see me, not the slightest surprise, not the slightest awkwardness.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/4/09.mp4"/>
<<TalkNPC _npc "Were you spying on me?">>
<<TalkMC "Just passing through.">>
<<TalkNPC _npc "Sure.">>
<<InformationUiPopUp>>I sit down on the small seat next to the bathtub. She goes back to what she was doing, rubbing her tits in front of me as if my presence were the most natural thing in the world.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/4/10.mp4"/>
<<TalkNPC _npc "Nothing better to do?">>
<<TalkMC "No.">>
<<TalkNPC _npc "That's fine, I'm glad to see you.">>
<<InformationUiPopUp>>She leans her torso slightly toward me, pushing her tits forward, with that smile.
<</InformationUiPopUp>>
<<InformationUiPopUp>>She's leaning on the edge of the bathtub, on her knees, swaying her hips slightly while we talk.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/4/11.mp4"/>
<<InformationUiPopUp>>I look at her and realize I have no intention of leaving. I stand up and position myself in front of her.
<</InformationUiPopUp>><</revealtext>>
<<revealtext "chapter5">><<InformationUiPopUp "Psychic Power" #7aa2ff>>You decide to use your power on <<=_npc.name>>.
<em>-1 Psychic Power</em><</InformationUiPopUp>>
<<TalkMC "Listen to me.">>
<<TalkMC "You enjoy my company so much that now you want more than just jerking me off or sucking me off. You want to fuck me. That's what you feel, that's what you want.">>
<<TalkNPC _npc "...">>
<<InformationUiPopUp>>She looks at me for a few seconds, then rises slightly in the bathtub and puts her hand on my cock through my trousers.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/4/12.mp4"/>
<<TalkNPC _npc "I've been thinking about it for a while.">>
<<TalkMC "About what?">>
<<TalkNPC _npc "About you, your cock, having some fun together.">>
<<InformationUiPopUp>>I pull my trousers down. She takes my cock and puts it in her mouth immediately, still on her knees in the water.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/4/13.mp4"/>
<<TalkNPC _npc "<em>Glrk... mmh... ghlk...</em>">>
<video src="assets/img/story/character/landlady/4/14.mp4"/>
<<TalkNPC _npc "<em>Mmh... glrk... mmh...</em>">>
<<InformationUiPopUp>>I crouch down, take her tits in my hands and bury my face in them, licking and sucking them. She laughs softly, letting me.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/4/15.mp4"/>
<<TalkNPC _npc "Ah... mmh...">>
<<InformationUiPopUp>>She steps out of the bathtub, still wet, and stands facing the sink, lifting one leg onto it, opening herself completely. I position myself behind her and push into her.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/4/16.mp4"/>
<<TalkNPC _npc "<em>Ah... yes... like that...</em>">>
<video src="assets/img/story/character/landlady/4/17.mp4"/>
<<TalkNPC _npc "<em>Ah... fuck... more...</em>">>
<<InformationUiPopUp>>I sit back down on the seat. She kneels in front of me and takes my cock back in her mouth.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/4/18.mp4"/>
<<TalkNPC _npc "<em>Glrk... mmh...</em>">>
<video src="assets/img/story/character/landlady/4/19.mp4"/>
<<TalkNPC _npc "<em>Ghlk...</em>">>
<<InformationUiPopUp>>She moves her face down to my balls, taking them in her mouth one at a time, gently jerking me off at the same time, eyes lifted to mine.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/4/20.mp4"/>
<<InformationUiPopUp>>She comes back up, presses her tits around my cock and starts making slow back and forth movements.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/4/21.mp4"/>
<<TalkMC "Incredible...">>
<video src="assets/img/story/character/landlady/4/22.mp4"/>
<<TalkNPC _npc "Mmh... you like that?">>
<<TalkMC "Come here.">>
<<InformationUiPopUp>>I lie down on the floor. She positions herself above me, facing away, in a squat, and slowly sinks onto my cock.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/4/23.mp4"/>
<<TalkNPC _npc "<em>Ah... it's so deep like this...</em>">>
<video src="assets/img/story/character/landlady/4/24.mp4"/>
<<TalkNPC _npc "<em>Ah... mmh... yes...</em>">>
<<InformationUiPopUp>>I take over, setting my own rhythm from below.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/4/25.mp4"/>
<<TalkNPC _npc "<em>Ah... fuck... more...</em>">>
<<InformationUiPopUp>>She turns around, in cowgirl this time. I keep setting my own rhythm and take her tits in my mouth.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/4/26.mp4"/>
<<TalkNPC _npc "<em>Ah... yes... keep going...</em>">>
<video src="assets/img/story/character/landlady/4/27.mp4"/>
<<InformationUiPopUp>>She takes over, squatting on top of me, thighs wide open, setting her own rhythm.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/4/28.mp4"/>
<<TalkNPC _npc "<em>Ah... ah... yes... yes...</em>">>
<<InformationUiPopUp>>I flip her onto all fours. I take her from behind.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/4/29.mp4"/>
<<TalkNPC _npc "<em>Ah... fuck... more...</em>">>
<<InformationUiPopUp>>I grab her hair with one hand and pull. She moans harder immediately.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/4/30.mp4"/>
<<TalkNPC _npc "<em>Ah... yes... like that...</em>">>
<<InformationUiPopUp>>She lowers her chest and head to the floor, ass raised completely, letting me go deeper.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/4/31.mp4"/>
<<TalkNPC _npc "<em>Ah... yes... keep going...</em>">>
<video src="assets/img/story/character/landlady/4/32.mp4"/>
<<TalkNPC _npc "<em>Ah... ah... yes... yes...</em>">>
<<InformationUiPopUp>>I flip her onto her back, kneel between her legs and push into her again.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/4/33.mp4"/>
<<TalkNPC _npc "<em>Ah... mmh... yes...</em>">>
<<InformationUiPopUp>>I gradually pick up the pace, until I end up coming on her chest and tits.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/4/34.mp4"/>
<<TalkNPC _npc "<em>Ah... ah... yes... yes...</em>">>
<<InformationUiPopUp>>She catches her breath, then scoops the cum up with her fingers and swallows it slowly, eyes on mine.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/4/35.mp4"/>
<<TalkNPC _npc "Mmh.">>
<<TalkMC "Good bath?">>
<<TalkNPC _npc "Better than usual.">><</revealtext>>
/* ====================================================
*
* ----------------------------------- CHAPTER 6 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 5>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><</if>>
<<passagebg>><<sound "bg" "bg.empty" true>><img src="assets/img/misc/home/mainbedroomnight.webp"/><</passagebg>>
<<InformationUiPopUp>>At night. I knock on her bedroom door.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/5/01.mp4"/>
<<TalkNPC _npc "Can't sleep?">>
<<TalkMC "No. Neither can you apparently.">>
<<TalkNPC _npc "I was reading. Come in if you want.">>
<<InformationUiPopUp>>She steps aside to let me in. We settle in the room, her on the bed, me on the seat. The bedside lamp is low, the house quiet around us.
<</InformationUiPopUp>>
<<TalkMC "You don't usually stay up this late.">>
<<TalkNPC _npc "Tonight my head was too full.">>
<<TalkMC "Of what?">>
<<TalkNPC _npc "Lots of things. My husband, work, the house. The kind of stuff that goes round and round when you're lying in the dark.">>
<<TalkMC "And right now, how do you feel?">>
<<TalkNPC _npc "Better. Weirdly better since you got here.">>
<<InformationUiPopUp>>She smiles saying that, without really trying to explain it. I know why. The effect of the power, always there the moment she's next to me.
<</InformationUiPopUp>>
<<TalkMC "Are you happy right now?">>
<<TalkNPC _npc "That's a strange question to ask at this hour.">>
<<TalkMC "Answer it anyway.">>
<<TalkNPC _npc "Honestly? Not really. I mean, my life is fine. I have a house, I have my husband, I have my routines. But something's been missing for a long time. I feel... switched off, most of the time.">>
<<TalkMC "And since I got here?">>
<<TalkNPC _npc "...">>
<<TalkNPC _npc "Since you got here it's different. I don't know how to explain it.">>
<<InformationUiPopUp>>She looks at her hands for a moment, then looks back up at me. I look at her, I have everything planned for tonight, I can put the final part of my plan into action, I know exactly what I want to do tonight. Once and for all.<</InformationUiPopUp>>
<<revealtext "chapter6">><<InformationUiPopUp "Psychic Power" #7aa2ff>>You decide to use your power on <<=_npc.name>>.
<em>-1 Psychic Power</em><</InformationUiPopUp>>
<<TalkMC "Listen to me.">>
<<TalkMC "You are completely submissive to me. You love it, it's exactly what you want. And from now on, you will call me Master.">>
<<TalkNPC _npc "...">>
<<InformationUiPopUp>>A few seconds. Her expression changes. The order settles into her, deep and final. She looks down, then looks back up at me differently.
<</InformationUiPopUp>>
<<TalkNPC _npc "What would you like to do, Master?">>
<<TalkMC "Do you have toys?">>
<<InformationUiPopUp>>She slides off the bed, kneels on the floor, and pulls a white box out from under the bed. She opens it in front of me.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/5/02.mp4"/>
<<InformationUiPopUp>>She takes the items out one by one, setting them on the bed. Ropes, handcuffs, a red ball gag, nipple clamps, a vibrator, a whip, a BDSM crop, etc.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/5/03.mp4"/>
<<TalkNPC _npc "I love BDSM, Master. But my husband doesn't like that kind of thing. I've been frustrated with him for a long time. But since you've been here, I feel happy. I feel alive again. And I will be absolutely at your service, whatever you want.">>
<<TalkMC "Perfect.">>
<<InformationUiPopUp>>I motion for her to come. She stands and approaches, kneels in front of me, eyes on mine, waiting.
<</InformationUiPopUp>>
<<InformationUiPopUp>>I take her face in my hands and give her small slaps on the cheek. She's already turned on, eyes bright.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/5/04.mp4"/>
<<TalkNPC _npc "Yes, Master.">>
<<InformationUiPopUp>>I press her back against me. I grab her shirt and rip the buttons off in one go, revealing her black lace bra.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/5/05.mp4"/>
<<InformationUiPopUp>>I hold her and push her onto the bed. I rip off her skirt, then spank her, one after another.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/5/06.mp4"/>
<<TalkNPC _npc "<em>Ah... yes... again, Master.</em>">>
<<InformationUiPopUp>>I grab her arms behind her back and hold her there while continuing the spanking.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/5/07.mp4"/>
<<TalkNPC _npc "<em>Ah... yes... Master...</em>">>
<<InformationUiPopUp>>I flip her over. I finish tearing her shirt, then rip off her bra.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/5/08.mp4"/>
<<InformationUiPopUp>>I hold her down on the bed, one hand on her face, the other slapping her tits one after the other.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/5/09.mp4"/>
<<TalkNPC _npc "<em>Ah... mmh... again, Master.</em>">>
<<InformationUiPopUp>>I pull off her black lace thong in one motion, and shove it in her mouth. She closes her lips around it without hesitating.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/5/10.mp4"/>
<<InformationUiPopUp>>I grab her legs, pull her toward the edge of the bed, spread her thighs, and spit on her pussy before rubbing it.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/5/11.mp4"/>
<<TalkNPC _npc "<em>Mmh... Master...</em>">>
<<InformationUiPopUp>>I put one hand on her throat, the other rubbing her pussy. She gives herself over completely, eyes half-closed.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/5/12.mp4"/>
<<InformationUiPopUp>>I stop, then pull her toward me and sit her against the bed. I pull out my cock, position myself in front of her face, and rest my balls on it. She licks and sucks them immediately.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/5/13.mp4"/>
<<TalkNPC _npc "<em>Mmh...</em>">>
<<InformationUiPopUp>>I push her to the other side, on her knees on the floor, her chest and face pressed against the seat, ass up. I spank her ass with my hand.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/5/14.mp4"/>
<<TalkNPC _npc "<em>Ah... yes... Master... again.</em>">>
<<InformationUiPopUp>>She gets back on her knees facing me, and takes my cock in her mouth, going deep every time.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/5/15.mp4"/>
<<TalkNPC _npc "<em>Glrk... mmh... ghlk...</em>">>
<video src="assets/img/story/character/landlady/5/16.mp4"/>
<<TalkNPC _npc "<em>Mmh... glrk... ghlk...</em>">>
<<InformationUiPopUp>>She sits back against a piece of furniture and keeps deep throating me, hands gripping the handles above her.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/5/17.mp4"/>
<<TalkNPC _npc "Master... please... slap me.">>
<<InformationUiPopUp>>I pull my cock out, then slap her on the cheeks and tits.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/5/18.mp4"/>
<<TalkNPC _npc "<em>Mmh... ah... yes... Master.</em>">>
<<InformationUiPopUp>>I sit her on the bed and put the gag on her, fastened behind her head. Then I push her to lay her down on her back.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/5/19.mp4"/>
<<InformationUiPopUp>>I take the handcuffs and cuff her wrists, then with the ropes I tie her ankles to the handcuffs, folding her in on herself.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/5/20.mp4"/>
<<InformationUiPopUp>>I finish tying her up, her pussy and ass wide open. I give her a few slaps on the pussy to get her even more worked up.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/5/21.mp4"/>
<<TalkNPC _npc "<em>Mmph... mmph...</em>">>
<<InformationUiPopUp>>I pull her to the edge of the bed and push into her pussy, standing in front of her.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/5/22.mp4"/>
<<TalkNPC _npc "<em>Mmph... mmh... mmph...</em>">>
<<InformationUiPopUp>>I decide to take the gag out to hear her come.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/5/23.mp4"/>
<<TalkNPC _npc "<em>Ah... yes... Master... again please...</em>">>
<<InformationUiPopUp>>I go around to the other side and put nipple clamps on her, connected to the handcuffs.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/5/24.mp4"/>
<<TalkNPC _npc "<em>Ah... Master... yes...</em>">>
<<InformationUiPopUp>>I come back in front of her and push into her pussy again.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/5/25.mp4"/>
<<TalkNPC _npc "<em>Ah... ah... yes... yes...</em>">>
<video src="assets/img/story/character/landlady/5/26.mp4"/>
<<TalkNPC _npc "<em>Master... again please...</em>">>
<<InformationUiPopUp>>I can see she's about to come, so to play with her, I stop, then switch holes and start fucking her ass slowly.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/5/27.mp4"/>
<<TalkNPC _npc "<em>Ah... ah... Master... yes...</em>">>
<video src="assets/img/story/character/landlady/5/28.mp4"/>
<<TalkNPC _npc "<em>Mmh... more, Master, fuck my ass.</em>">>
<video src="assets/img/story/character/landlady/5/29.mp4"/>
<<TalkNPC _npc "<em>Ah... yes... Master...</em>">>
<<InformationUiPopUp>>I stop again, remove the nipple clamps, then take the vibrator and press it directly against her pussy. She shudders violently at the first contact.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/5/30.mp4"/>
<<TalkNPC _npc "<em>Ah... Master... it's too much...</em>">>
<<InformationUiPopUp>>At the same time I slap her tits.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/5/31.mp4"/>
<<TalkNPC _npc "<em>Ah... ah... yes... Master... fuck... more...</em>">>
<<InformationUiPopUp>>She ends up coming, eyes rolling back. I pinch her nipples at the same time.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/5/32.mp4"/>
<<TalkNPC _npc "<em>Ah... ah... yes... yes... Master...</em>">>
<<InformationUiPopUp>>I hold her hair with one hand, vibrator still pressed against her.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/5/33.mp4"/>
<<TalkNPC _npc "<em>Ah... Master... more... please... keep treating me like this, please!</em>">>
<video src="assets/img/story/character/landlady/5/34.mp4"/>
<<TalkNPC _npc "<em>Ah... ah... yes... yes...</em>">>
<<InformationUiPopUp>>I put a hand on her throat and keep the vibrator pressed against her. She comes hard, her legs going straight. The moment she comes, I pull my hand and the vibrator away at once.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/5/35.mp4"/>
<<TalkNPC _npc "<em>Ah... Fuck! Fuck! Thank you Master... fuck, thank you, I love you so much Master!</em>">>
<<InformationUiPopUp>>I untie her and retie her differently, arms bound behind her back, the rope passing between her tits. She's on her knees, chest and face on the floor, ass up. I pick up the BDSM crop and hit her ass with it.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/5/36.mp4"/>
<<TalkNPC _npc "<em>Ah... yes... Master... again.</em>">>
<<InformationUiPopUp>>I pull her back up, still on her knees, grab her head and push my cock into her mouth.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/5/37.mp4"/>
<<TalkNPC _npc "<em>Glrk... mmh... ghlk...</em>">>
<video src="assets/img/story/character/landlady/5/38.mp4"/>
<<TalkNPC _npc "<em>Mmh... glrk...</em>">>
<<InformationUiPopUp>>I deep throat her, she drools.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/5/39.mp4"/>
<<TalkNPC _npc "<em>Glrk... mmh...</em>">>
<<InformationUiPopUp>>I pull her back up and set her on her knees, head pressed against the couch, ass up. I push into her pussy again from behind.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/5/40.mp4"/>
<<TalkNPC _npc "<em>Ah... Master... yes...</em>">>
<video src="assets/img/story/character/landlady/5/41.mp4"/>
<<TalkNPC _npc "<em>Ah... ah... yes... yes...</em>">>
<<InformationUiPopUp>>She's lying on her side, right leg raised toward the ceiling. I keep fucking her pussy, one hand on her face pressing it against the couch.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/5/42.mp4"/>
<<TalkNPC _npc "<em>Ah... Master... fuck... more... fuck me like the dirty slut I am!</em>">>
<<InformationUiPopUp>>I sit on her, balls on her face. She immediately licks my balls and ass, eyes open looking up at me, focused on what she's doing.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/5/43.mp4"/>
<<TalkNPC _npc "<em>Mmh...</em>">>
<<InformationUiPopUp>>She keeps going while I rub her pussy. Then I pull away and bring her up, placing her on the floor, knees and face against the floor, ass up.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/5/44.mp4"/>
<<TalkNPC _npc "<em>Come on Master, fuck me like the dirty bitch I am!</em>">>
<<InformationUiPopUp>>I position myself behind her, grab her hips, and fuck her doggy style.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/5/45.mp4"/>
<<TalkNPC _npc "<em>Ah... Master... yes...</em>">>
<<InformationUiPopUp>>I keep going, then grab her by the arms behind her back and pull her torso up while still fucking her.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/5/46.mp4"/>
<<TalkNPC _npc "<em>Ah... ah... fuck... Master...</em>">>
<<InformationUiPopUp>>I grab her by the throat to move her back onto the couch in the same position, then get back behind her.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/5/47.mp4"/>
<<TalkNPC _npc "Please, Master, fuck my ass again, please.">>
<<TalkMC "Shut it, I'll fuck your ass when I feel like it, but you're lucky because that's exactly what I had in mind.">>
<<TalkNPC _npc "Yes, sorry Master, forgive me, it just turns me on too much.">>
<<InformationUiPopUp>>I push my cock into her ass and fuck her.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/5/48.mp4"/>
<<TalkNPC _npc "<em>Ah... Master... it's so deep...</em>">>
<<TalkMC "You know what, you deserve to be punished for what you just said.">>
<<TalkNPC _npc "Sorry Master, I'm just a dirty slut, punish me.">>
<<InformationUiPopUp>>I stop and go get the whip. I come back and whip her ass with it.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/5/49.mp4"/>
<<TalkNPC _npc "Master... please...">>
<<TalkMC "Please what?">>
<<TalkNPC _npc "Please keep going, I'm really sorry, I'm just a filthy slut.">>
<<InformationUiPopUp>>I finish whipping her, then flip her onto her back, legs spread wide, and fuck her ass again from this position.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/5/50.mp4"/>
<<TalkNPC _npc "<em>Ah... yes... Master... more...</em>">>
<video src="assets/img/story/character/landlady/5/51.mp4"/>
<<TalkNPC _npc "<em>Ah... ah... yes... yes... Master...</em>">>
<<InformationUiPopUp>>I pull my cock out and lift her ass up, her ass gaping wide open in front of me. Then I bring her back up, put her on her knees on the floor, and stand in front of her. I jerk off in front of her, she understands immediately and opens her mouth wide, tongue out, waiting for me to finish.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/5/52.mp4"/>
<<InformationUiPopUp>>I end up coming, aiming for her mouth. She takes it all, mouth wide open, tongue out, then sucks my cock to get every last drop of cum and swallows everything.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/5/53.mp4"/>
<<TalkNPC _npc "Aaaah, thank you Master.">>
<<InformationUiPopUp>>I untie her completely, then we both sit on the couch, still naked. I put a hand on her tits, she fondles them in turn, completely relaxed, smiling.
<</InformationUiPopUp>>
<video src="assets/img/story/character/landlady/5/54.mp4"/>
<<TalkNPC _npc "That was... exactly what I'd needed for a long time.">>
<<TalkMC "I can see that, you look completely at peace.">>
<<TalkNPC _npc "Now I belong to you Master. Completely, my mind, my body, I'm all yours.">>
<<InformationUiPopUp>>The room is quiet around us again. While the night continues outside.
<</InformationUiPopUp>><</revealtext>>
/* ====================================================
*
* -------------------------------- REPLAY CHAPTER --------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl > 5>><<set $SaveTalklvl = _npc.talklvl>><<set _npc.replaytalk = true>><<set _gotoReplayNpc = "Talk." + _npc.id>>
<<passagebg>><img src="assets/background.gif"/><</passagebg>>
<style>.rCard a{display:flex;align-items:center;gap:clamp(6px,1vw,10px);padding:clamp(8px,1.2vw,11px) clamp(10px,1.5vw,16px);border-radius:10px;background:rgba(230,87,99,.07);border:1px solid rgba(230,87,99,.18);text-decoration:none;transition:background .15s;}.rCard a:hover{background:rgba(230,87,99,.14);border-color:rgba(230,87,99,.35);}.rCard .rNum{font-size:calc(clamp(14px,1.8vw,18px) + var(--font-boost,0px));font-weight:950;color:rgba(255,255,255,.92);}.rCard .rLabel{font-size:calc(clamp(9px,1vw,12px) + var(--font-boost,0px));font-weight:900;letter-spacing:.16em;text-transform:uppercase;color:rgba(230,87,99,.55);}.rCard .rArrow{margin-left:auto;font-size:calc(clamp(9px,1vw,12px) + var(--font-boost,0px));font-weight:900;letter-spacing:.1em;color:rgba(230,87,99,.45);}</style><div style="display:flex;flex-direction:column;gap:6px;width:100%;margin-top:6px;"><div style="font-size:calc(clamp(9px,1vw,12px) + var(--font-boost,0px));font-weight:900;letter-spacing:.16em;text-transform:uppercase;color:rgba(255,255,255,.18);margin-bottom:6px;text-align:center;">— Select a scene to replay —</div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>01</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 0>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>02</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 1>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>03</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 2>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>04</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 3>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>05</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 4>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>06</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 5>><<goto _gotoReplayNpc>><</link>></div></div>
<</if>><</if>><div class="BottomUiBarCustom">
<<if _npc.talklvl == 0>><<BottomButton "Decision">><<revealbtn "wakeup" "🥱 Wake up" "" "" "power1" true>><</revealbtn>><<revealbtn "chapter1" "🧠 Use power" "moveBtn" "power1" "" false>><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 1>><<BottomButton "Decision">><<revealbtn "chapter2" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 2>><<BottomButton "Decision">><<revealbtn "golivingroom" "➡️ Go to the Living Room" "" "" "power3" true>><</revealbtn>><<revealbtn "chapter3" "🧠 Use power" "moveBtn" "power3" "" false>><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 3>><<BottomButton "Decision">><<revealbtn "chapter4" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 4>><<BottomButton "Decision">><<revealbtn "enterbathroom" "➡️ Enter in the Bathroom" "" "" "power5" true>><</revealbtn>><<revealbtn "chapter5" "🧠 Use power" "moveBtn" "power5" "" false>><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 5>><<BottomButton "Decision">><<revealbtn "chapter6" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><</if>>
<<BottomButton "Move" "moveBtn">><<if $FromOtherPlace == true>><<link "↩️ Return">><<if _npc.replaytalk == false>><<set _npc.talklvl++>><<set _npc.lvl++>><<set $PsychicPower -= 1>><<if _NextTime == true>><<set $Time++>><<set _NextTime = false>><</if>><<else>><<set _npc.talklvl = $SaveTalklvl>><<set _npc.replaytalk = false>><</if>><<ReturnToGoto>><<set $FromOtherPlace = false>><</link>><<else>><<link "↩️ Return">><<if _npc.replaytalk == false>><<set _npc.talklvl++>><<set _npc.lvl++>><<set $PsychicPower -= 1>><<if _NextTime == true>><<set $Time++>><<set _NextTime = false>><</if>><<else>><<set _npc.talklvl = $SaveTalklvl>><<set _npc.replaytalk = false>><</if>><<bgpause>><<goto _gotoNpc>><</link>><</if>><</BottomButton>>
</div><<sound "music" "music.music" true>><<set _raw = $ActiveNPC>><<if !_raw or _raw.id is undefined>>Invalid NPC.<<else>><<set _id = String(_raw.id)>><<set _key = "NPC" + _id>><<run State.temporary.npcObj = State.variables[State.temporary.key] || State.variables[_key]>><<set _npc = _npcObj>><<set _gotoNpc = _npc.id + ".interact">>
/* ====================================================
*
* ----------------------------------- CHAPTER 1 -----------------------------------------
*
*/ ====================================================
<<if _npc.talklvl == 0>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><</if>>
<<passagebg>><<sound "bg" "bg.empty" true>><img src="assets/img/misc/home/bathroom/bathroom.webp"/><</passagebg>>
<<InformationUiPopUp>>The morning light filters through the hallway as I make my way to the bathroom, still half-asleep. I reach out and push the door open without thinking, not bothering to knock. The door swings wide open before I even realize my mistake.
<</InformationUiPopUp>>
<video src="assets/img/story/character/housematefemale/0/01.mp4"/>
<<TalkNPC _npc "What the... get out! Are you serious right now?!">>
<<InformationUiPopUp>><<=_npc.name>> spins around, clearly startled, her expression shifting instantly from surprise to anger. She grabs a towel from the rack and clutches it tightly against her, glaring at me like I just committed a crime.
<</InformationUiPopUp>>
<<TalkMC "Hey, sorry, I didn't know you were in here. The door wasn't locked.">>
<<TalkNPC _npc "Oh, so that makes it okay? You just get to walk right in? Really?">>
<<TalkMC "I'm not trying to start anything. I just woke up and needed the bathroom. That's it.">>
<<TalkNPC _npc "Sure. Sure. You always manage to be exactly where you're not supposed to be, don't you?">>
<<InformationUiPopUp>>I step back into the hallway, keeping the door half-closed between us as a gesture of goodwill. She doesn't look convinced. Her voice has that familiar sharpness she uses whenever she has to deal with me.
<</InformationUiPopUp>>
<<TalkMC "Look, I'm genuinely sorry. I should have knocked. That's on me.">>
<<TalkNPC _npc "Knocked? You should have checked if the light was on. Basic stuff, honestly.">>
<<TalkMC "You're right. I wasn't thinking straight, I just woke up. Won't happen again.">>
<<InformationUiPopUp>>A brief silence settles between us. I can hear her moving behind the door, the water still running in the background.
<</InformationUiPopUp>>
<<TalkNPC _npc "That's what you say. But I swear you do this kind of thing on purpose. Like you actually enjoy making people uncomfortable.">>
<<TalkMC "Why would I do that? What would I even get out of it?">>
<<TalkNPC _npc "I don't know, you tell me. You always seem to show up at the worst possible moment.">>
<<TalkMC "That's not something I plan. I live here too. We share the same hallway, the same bathroom, the same kitchen. These things happen.">>
<<TalkNPC _npc "They happen a little too often with you.">>
<<InformationUiPopUp>>Her voice rises a notch. I can feel this spiraling fast if I let it keep going. I could apologize again, but she wouldn't hear it. Not in this state.
So I make a different call.
<</InformationUiPopUp>>
<<revealtext "chapter1">><<InformationUiPopUp "Psychic Power" #7aa2ff>>You decide to use your power on <<=_npc.name>>.<<if _npc.replaytalk == false>>
<em>-1 Psychic Power</em><</if>>
<</InformationUiPopUp>>
<<TalkMC "Listen to me.">>
<<InformationUiPopUp>>My voice shifts slightly, something steadier, more deliberate. I hold her gaze and choose each word with care.
<</InformationUiPopUp>>
<<TalkMC "You're going to forget your anger toward me. And from now on, you won't be bothered if I walk into the bathroom while you're in it.">>
<<TalkNPC _npc "Huh? What are y-">>
<<InformationUiPopUp>>She stops mid-sentence. Like something just disconnected inside her. Her eyes drift for a fraction of a second, her jaw slightly slack. Then she blinks, and when her gaze finds me again, all the hostility is gone.
<</InformationUiPopUp>>
<<TalkNPC _npc "Oh, um...">>
<<TalkNPC _npc "What are you doing here?">>
<<InformationUiPopUp>>Her voice is neutral. Not cold, not warm. Just... normal. As if everything that just happened never did.
<</InformationUiPopUp>>
<<TalkMC "Just needed to use the bathroom. Mind if I do?">>
<<TalkNPC _npc "Oh. Yeah, sure.">>
<<InformationUiPopUp>>She turns back around, pulls the shower curtain closed behind her, and resumes her shower like my presence is the most natural thing in the world. No discomfort, no hesitation.
I stand there for a second, a little thrown by how easily that worked.
<</InformationUiPopUp>>
<<InformationUiPopUp>>When I'm done, I slip out of the bathroom a few moments before her. <<=_npc.name>> emerges shortly after, walks past me in the hallway without a glance.
<</InformationUiPopUp>>
<video src="assets/img/story/character/housematefemale/0/02.mp4"/>
<<InformationUiPopUp>>She disappears into her room and the door closes behind her with a soft click. I stay in the hallway for a moment, exhaling slowly.
Not a great start to the morning. But it could have gone much worse.
She doesn't like me. That's always been clear. But today, for the first time, I felt what my power is actually capable of. She followed the order without a trace of resistance, without even realizing it. If it's really that simple...
I find myself wondering how far I could take this.
<</InformationUiPopUp>><</revealtext>>
/* ====================================================
*
* ----------------------------------- CHAPTER 2 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 1>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><</if>>
<<passagebg>><<sound "bg" "bg.classroom" true>><img src="assets/img/misc/university/class2.webp"/><</passagebg>>
<<InformationUiPopUp>>The lecture hall is packed as usual, rows of students filling the tiered seats with their laptops and notebooks. I spot an empty seat next to <<print _npc.name>> near the middle section and make my way over. She glances up as I sit down, and her expression carries that familiar guardedness, though something about it feels slightly less sharp than it used to.
<</InformationUiPopUp>>
<<TalkMC "Hey. Mind if I sit here?">>
<<TalkNPC _npc "There are like fifty other seats available.">>
<<TalkMC "Yeah, but this one's next to someone I know.">>
<<TalkNPC _npc "We barely know each other.">>
<<InformationUiPopUp>>She's not really leaving me a choice. I could push back, find an argument, but I already know how that ends. If I want to get closer to her, I'm going to need a little help.
<</InformationUiPopUp>>
<<revealtext "chapter2">><<InformationUiPopUp "Psychic Power" #7aa2ff>>You decide to use your power on <<=_npc.name>>.<<if _npc.replaytalk == false>>
<em>-1 Psychic Power</em><</if>>
<</InformationUiPopUp>>
<<TalkMC "Listen to me.">>
<<InformationUiPopUp>>I lower my voice slightly, just enough to keep it between the two of us.
<</InformationUiPopUp>>
<<TalkMC "From now on, you won't have any problem with me being next to you. You'll actually be glad I'm here, like with a good friend.">>
<<InformationUiPopUp>><<=_npc.name>> stays still for a moment, her gaze fixed on her laptop screen without really seeing it. Her shoulders ease slightly. Then she blinks, and when she looks back at me, something in her expression has shifted.
<</InformationUiPopUp>>
<<TalkNPC _npc "...">>
<<TalkNPC _npc "Did you want to sit down?">>
<<TalkMC "Yeah, if that's okay with you.">>
<<TalkNPC _npc "Of course, go ahead. No problem at all.">>
<<TalkNPC _npc "You're in this class? I've never seen you here before.">>
<<TalkMC "I usually sit in the back. Easier to stay under the radar back there.">>
<<TalkNPC _npc "And today you decided to change things up?">>
<<TalkMC "Let's say I felt like a bit of company for once.">>
<<InformationUiPopUp>>She gives a small smile without responding and goes back to her notes. The conversation flows naturally between us until the professor arrives and starts the lecture. For a while we both fall quiet, taking notes at roughly the same pace. A few times I notice <<=_npc.name>> underlining something, and I find myself glancing over to see if I missed an important point. She notices once and tilts her screen slightly toward me, without a word. A small gesture, but a deliberate one.
<</InformationUiPopUp>>
<<TalkMC "Thanks.">>
<<TalkNPC _npc "I didn't do anything.">>
<<TalkMC "Sure.">>
<<InformationUiPopUp>>The lecture wraps up forty minutes later and the hall fills with the noise of people packing up, chairs scraping, voices layering over each other. <<=_npc.name>> closes her laptop and slides it into her bag with practiced efficiency.
<</InformationUiPopUp>>
<<TalkNPC _npc "You actually took notes. I'm a little surprised.">>
<<TalkMC "Of course. Even if I don't always show it, I'm someone who takes things seriously.">>
<<TalkNPC _npc "Didn't exactly come across that way from the back of the room.">>
<<TalkMC "Sitting in the back is strategic. Not lazy.">>
<<InformationUiPopUp>>She rolls her eyes, but without any real edge behind it. She stands, slinging her bag over her shoulder, and I follow her out toward the side exit. The crowd filters through the wide doors slowly, people bunching up near the exit. We end up walking side by side through the bottleneck, shoulders nearly touching.
<</InformationUiPopUp>>
<<InformationUiPopUp>>We pass through the exit and into the corridor, the crowd gradually thinning around us. The conversation flows far more naturally than it would have a few days ago. She's relaxed, almost playful at moments. My power is clearly doing its job, though I find myself wondering how deep it actually goes.
<</InformationUiPopUp>>
<<InformationUiPopUp>>We stop near the point where the corridor splits, our directions diverging. She adjusts her bag strap and turns halfway toward me.
<</InformationUiPopUp>>
<<TalkNPC _npc "Same class next week?">>
<<TalkMC "I'll even do the reading.">>
<<TalkNPC _npc "Two weeks in a row. Truly remarkable.">>
<<InformationUiPopUp>>She turns to leave. Partly out of curiosity, partly to test the limits of what my power has changed in her, I reach out and give her a quick smack on the ass. She stops dead. A beat of silence. Then she turns her head back toward me, one eyebrow raised, her expression caught somewhere between surprised and something else she's working to keep neutral.
<</InformationUiPopUp>>
<video src="assets/img/story/character/housematefemale/1/01.mp4"/>
<<TalkNPC _npc "Did you just... okay. That was bold.">>
<<TalkMC "Too bold?">>
<<TalkNPC _npc "I haven't decided yet.">>
<<TalkMC "Let me know when you do.">>
<<InformationUiPopUp>>She holds my gaze for a second longer than necessary, then turns back around and walks off down the corridor. She doesn't say anything else, but she doesn't seem angry either. There's a slight shift in how she carries herself as she walks away, something subtle, almost like she's choosing not to look back but thinking about it anyway.
I watch her go for a moment, then turn toward my own direction. The line between what my power created and what's real is starting to blur. And honestly, I'm pretty sure that with this, I could get exactly what I want.
<</InformationUiPopUp>><</revealtext>>
/* ====================================================
*
* ----------------------------------- CHAPTER 3 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 2>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<if $Inventory.alcool and $Inventory.alcool.qty >= 2>><<set $Inventory.alcool.qty -= 2>><<if $Inventory.alcool.qty <= 0>><<run delete State.variables.Inventory.alcool>><</if>><</if>><<set _NextTime = true>><</if>>
<<passagebg>><<sound "bg" "bg.neighborhood" true>><img src="assets/img/misc/home/garden.webp"/><</passagebg>>
<<InformationUiPopUp>>The afternoon is warm and quiet. At the back of the garden, I can see that <<print _npc.name>> has set up a small camping tent. I grab two beers from the kitchen and head outside, spotting her already sitting cross-legged at the tent entrance, scrolling through her phone with her shoes off.
<</InformationUiPopUp>>
<<TalkMC "Since when do we have a tent?">>
<<TalkNPC _npc "Since I needed somewhere to sit that wasn't my room or the living room.">>
<<TalkMC "So you built yourself a third room in the garden.">>
<<TalkNPC _npc "Basically, yes.">>
<<InformationUiPopUp>>I hand her a beer and she takes it without hesitation. I sit down beside her at the tent entrance, close enough that our shoulders are almost touching. The garden around us is still, except for the occasional sound of wind moving through the leaves.
<</InformationUiPopUp>>
<<TalkNPC _npc "You actually came outside voluntarily. No screen, no headphones.">>
<<TalkMC "It happens a lot more than you think.">>
<<TalkNPC _npc "Name one other time.">>
<<TalkMC "I'm working on the list.">>
<<TalkNPC _npc "As expected.">>
<<InformationUiPopUp>>She smiles and leans back on her hands, tilting her face slightly up toward the sky. The warmth of the afternoon settles around us and neither of us feels the need to fill every second with words. It's comfortable in a way that still surprises me a little, given where we started.
<</InformationUiPopUp>>
<<TalkMC "You like being outside. You come out here a lot.">>
<<TalkNPC _npc "It helps me think. Inside the house everything feels a little... contained. Out here it's easier to breathe.">>
<<TalkMC "I know what you mean.">>
<<TalkNPC _npc "Do you? You spend most of your time indoors.">>
<<TalkMC "Doesn't mean I don't understand the appeal of escaping it.">>
<<TalkNPC _npc "Fair point.">>
<<InformationUiPopUp>>She laughs softly and shifts slightly, turning just enough toward me that the space between us closes a little more. Her posture is relaxed, open, a version of her I didn't see at all in those first weeks of living together.
<</InformationUiPopUp>>
<<TalkNPC _npc "Things have been different lately. Between us, I mean.">>
<<TalkMC "Different good or different strange?">>
<<TalkNPC _npc "Both maybe. But... mostly good.">>
<<TalkMC "That's good to hear.">>
<<TalkNPC _npc "Don't read too much into it.">>
<<InformationUiPopUp>>I'm looking for a way to push things a little further without rushing it. And then an idea comes to me. Simple, effective.
<</InformationUiPopUp>>
<<TalkMC "Feel like playing a game?">>
<<TalkNPC _npc "What do you mean? What game?">>
<<TalkMC "Truth or dare.">>
<video src="assets/img/story/character/housematefemale/2/01.mp4"/>
<<TalkNPC _npc "You're unbelievable...">>
<<TalkMC "Come on, it'll pass the time and it's fun. We get jokers, but if you use one, you drink. Deal?">>
<<TalkNPC _npc "...">>
<<TalkNPC _npc "Ok. But nothing weird.">>
<<TalkMC "As a show of good faith, I'll let you go first.">>
<<TalkNPC _npc "Ok. Truth or dare?">>
<<revealtext "chapter3Dare">><<TalkMC "Dare.">>
<<TalkNPC _npc "Ok. Do 20 push-ups.">><</revealtext>><<revealtext "chapter3DareJoker">><br><<TalkMC "Joker. Way too tired for that.">>
<<TalkNPC _npc "Pffff. Go on then, take a sip.">>
<<InformationUiPopUp>>I take a sip of my beer with an exaggerated grimace. She rolls her eyes, amused. My turn.
<</InformationUiPopUp>><</revealtext>><<revealtext "chapter3DareYes">><br><<TalkMC "No problem.">>
<<InformationUiPopUp>>I get up and get into position. She watches me with a smirk, looking like she expects me to stop at five.
<</InformationUiPopUp>>
<<TalkMC "1... 2... 3... 4...">>
<<InformationUiPopUp "Fitness">><em>+1 Fitness</em><<set $Fitness++>>
<</InformationUiPopUp>>
<<InformationUiPopUp>>I finish the set without too much trouble. She looks mildly impressed, even if she'll never admit it. My turn.
<</InformationUiPopUp>><</revealtext>><<revealtext "chapter3Truth">><<TalkMC "Truth.">>
<<TalkNPC _npc "Alright. What do you think of me?">><</revealtext>><<revealtext "chapter3TruthJoker">><br><<TalkMC "Joker.">>
<<TalkNPC _npc "Seriously? You're no fun...">>
<<TalkNPC _npc "Take a sip.">>
<<InformationUiPopUp>>I do. She shakes her head, smiling despite herself. My turn.
<</InformationUiPopUp>><</revealtext>><<revealtext "chapter3TruthYes">><br><<TalkMC "I think you're a good person. We got off to a rough start, but things have really improved between us. I hope it stays that way.">>
<<TalkNPC _npc "Mmh. Ok, I'll take that.">>
<<InformationUiPopUp>>She looks away for a second, but I catch the small smile she's trying to hide. My turn.
<</InformationUiPopUp>><</revealtext>><<revealtext "chapter3ToD">><br><<TalkMC "My turn. Truth or dare?">>
<<TalkNPC _npc "Dare.">>
<<InformationUiPopUp>>I decide to go for it. Calmly, but clearly.
<</InformationUiPopUp>>
<<TalkMC "I want you to touch me with your hand.">>
<<TalkNPC _npc "Are you serious? You're doing that thing again.">>
<<TalkMC "What thing?">>
<<TalkNPC _npc "You push and push and wait to see what happens. Except this time you're going way too far!">>
<<InformationUiPopUp>>Her reaction is exactly what I expected. I moved too fast, too directly. If I leave it like this, the whole afternoon is ruined. I'm going to need a little push.
<</InformationUiPopUp>><</revealtext>><<revealtext "chapter3">><br><<InformationUiPopUp "Psychic Power" #7aa2ff>>You decide to use your power on <<=_npc.name>>.<<if _npc.replaytalk == false>>
<em>-1 Psychic Power</em><</if>>
<</InformationUiPopUp>>
<<TalkMC "Listen to me. You're going to calm down and accept this dare. And you're going to do it willingly.">>
<<InformationUiPopUp>>As usual, she goes still. Eyes distant for a few seconds, shoulders dropping. Then she comes back, and something in her expression has shifted.
<</InformationUiPopUp>>
<<TalkNPC _npc "...">>
<<TalkNPC _npc "Fine... I'll go along with it this time.">>
<<InformationUiPopUp>>A faint blush rises to her cheeks. She looks away for a moment, then brings her eyes back to me, her voice carrying a hesitation that sounds different from usual.
<</InformationUiPopUp>>
<<TalkNPC _npc "Um... Uh... Pull your pants down... Please...">>
<video src="assets/img/story/character/housematefemale/2/02.mp4"/>
<<InformationUiPopUp>>The order did its job, as expected.
<</InformationUiPopUp>>
<<TalkMC "Ok, there you go.">>
<video src="assets/img/story/character/housematefemale/2/03.mp4"/>
<<InformationUiPopUp>>Her grip is light at first, unhurried, like she's setting her own pace from the start. She keeps her eyes focused, occasionally glancing up at me with an expression that's hard to read but not disinterested. Her hand moves slowly, building gradually, and I let my head fall back slightly against the tent fabric.
<</InformationUiPopUp>>
<<TalkMC "Oh damn...">>
<<TalkMC "Keep going, don't stop...">>
<video src="assets/img/story/character/housematefemale/2/04.mp4"/>
<<TalkMC "Argh... I'm close!">>
<image src="assets/img/story/character/housematefemale/2/05.webp"/>
<<TalkNPC _npc "Oh, wow.">>
<<TalkNPC _npc "Good? Happy?">>
<<TalkMC "Perfect.">>
<<InformationUiPopUp>>She wipes her hand and picks her beer back up, settling into her earlier position like the afternoon simply continued without interruption. I pull my jeans back on and lean back beside her, the two of us quiet again. The garden is the same as it was before. Except that it isn't, not quite.
<</InformationUiPopUp>>
<<TalkNPC _npc "Hm... We could do this again another time if you want...">>
<<TalkMC "With pleasure.">>
<<InformationUiPopUp>>She smiles, small and private, looking out at the garden rather than at me. The late afternoon light stretches across the grass, golden and still. Neither of us moves to go inside for a long while.
<</InformationUiPopUp>><</revealtext>>
/* ====================================================
*
* ----------------------------------- CHAPTER 4 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 3>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><</if>>
<<passagebg>><<sound "bg" "bg.neighborhood" true>><img src="assets/img/misc/home/garden.webp"/><</passagebg>>
<<InformationUiPopUp>>The afternoon is warm and quiet. I step outside into the garden and find <<print _npc.name>> already lying on a large blanket spread across the grass, looking up at the sky. The moment she hears me, she turns her head and smiles, a warm, open smile that she doesn't bother hiding.
<</InformationUiPopUp>>
<<TalkNPC _npc "Hey, I was hoping you'd come outside.">>
<<TalkMC "Yeah?">>
<<TalkNPC _npc "I saved you a spot.">>
<<TalkMC "I can see that.">>
<<TalkNPC _npc "Come lie down, it's really nice out.">>
<<InformationUiPopUp>>I settle down beside her on the blanket. She shifts closer immediately, her shoulder against mine, comfortable and deliberate about it.
<</InformationUiPopUp>>
<video src="assets/img/story/character/housematefemale/3/01.mp4"/>
<<TalkMC "Good afternoon?">>
<<TalkNPC _npc "Better now. The seminar was brutal, the professor ran over by half an hour and I spent the whole time just wanting to come back.">>
<<TalkMC "Come back here specifically?">>
<<TalkNPC _npc "Come back to see you, yeah.">>
<<TalkMC "That's new.">>
<<TalkNPC _npc "Is that a problem?">>
<<TalkMC "Not at all.">>
<<TalkNPC _npc "Good. Because I've been thinking about you all afternoon, honestly.">>
<<TalkMC "Thinking about me how?">>
<<TalkNPC _npc "Don't make me spell it out.">>
<<TalkMC "I want to hear you say it.">>
<<TalkNPC _npc "Fine. I've been thinking about what we did last time. Happy?">>
<<TalkMC "Very.">>
<<TalkNPC _npc "You're impossible.">>
<<TalkMC "And yet you've been thinking about me all afternoon.">>
<<TalkNPC _npc "Shut up.">>
<<InformationUiPopUp>>She laughs softly and rolls onto her side to face me, propping herself up on one elbow. Her eyes move over my face with an openness she wouldn't have shown before, making no effort to disguise it.
That's when the idea comes to me. She's already been thinking about it on her own, the ground is fertile. Might as well use that to push things one step further.
<</InformationUiPopUp>>
<<revealtext "chapter4">><<InformationUiPopUp "Psychic Power" #7aa2ff>>You decide to use your power on <<=_npc.name>>.<<if _npc.replaytalk == false>>
<em>-1 Psychic Power</em><</if>>
<</InformationUiPopUp>>
<<TalkMC "Listen to what I'm about to tell you.">>
<<TalkMC "Right now, you have an irresistible desire for me. And not just to touch me.">>
<<InformationUiPopUp>>Her gaze drifts for two or three seconds, her shoulders dropping slightly. Then she comes back. And when her eyes settle on me again, they're different. More intense, more direct.
<</InformationUiPopUp>>
<<TalkNPC _npc "...">>
<<TalkNPC _npc "Can I kiss you?">>
<<TalkMC "You're asking now?">>
<<TalkNPC _npc "I'm being polite.">>
<<TalkMC "Then yes.">>
<<InformationUiPopUp>>She leans in and kisses me, warm and immediate, her free hand coming up to my jaw to hold me in place. It isn't a tentative kiss, it's one that knows exactly what it wants.
<</InformationUiPopUp>>
<video src="assets/img/story/character/housematefemale/3/02.mp4"/>
<<InformationUiPopUp>>She pulls back just enough to look at me, then swings one leg over and straddles my hips, settling her weight down on top of me as I lie on my back. She rolls her hips once, slowly, then leans back down to kiss me deeper, harder, her hands pressing flat against my chest.
<</InformationUiPopUp>>
<video src="assets/img/story/character/housematefemale/3/03.mp4"/>
<<TalkNPC _npc "I've wanted to do this since this morning.">>
<<TalkMC "You should have said something.">>
<<TalkNPC _npc "I'm saying it now.">>
<<TalkMC "Fair enough.">>
<<InformationUiPopUp>>She kisses me once more, then pulls back and begins moving down my body, her hands dragging slowly down my chest and stomach with clear purpose. She reaches my waistband and looks up at me, her expression focused and wanting.
<</InformationUiPopUp>>
<<TalkNPC _npc "I want to taste you.">>
<<TalkMC "Go ahead.">>
<<InformationUiPopUp>>She pulls my jeans and underwear down without hesitation, wraps one hand around me, strokes slowly once, then leans down and takes me into her mouth. She lets out a quiet sound as she does it, like this is something she has been looking forward to.
<</InformationUiPopUp>>
<video src="assets/img/story/character/housematefemale/3/04.mp4"/>
<video src="assets/img/story/character/housematefemale/3/05.mp4"/>
<<TalkMC "<<print _npc.name>>.">>
<<TalkNPC _npc "Mm, don't hold back. I want to hear you.">>
<<InformationUiPopUp>>She takes her time, slow at first, her tongue moving with intention, her hand following the rhythm of her mouth. She looks up at me frequently, holds eye contact, watching my reaction with visible satisfaction each time she draws one out.
<</InformationUiPopUp>>
<video src="assets/img/story/character/housematefemale/3/06.mp4"/>
<<TalkMC "Deeper.">>
<<TalkNPC _npc "Mm.">>
<<InformationUiPopUp>>She responds immediately, taking me deeper, her pace picking up without needing to be asked twice. One hand grips my thigh for leverage and she moves with more intensity now, entirely focused on drawing out every reaction she can get.
<</InformationUiPopUp>>
<video src="assets/img/story/character/housematefemale/3/07.mp4"/>
<<TalkMC "Don't stop.">>
<<TalkNPC _npc "Wasn't planning to.">>
<<InformationUiPopUp>>She pushes the pace further, relentless and attentive, adjusting every time she feels my grip tighten in her hair, reading every signal and responding to each one. The tension coils tight and then breaks, and I finish hard into her mouth. She takes everything without pulling back, swallows without hesitation, and only lifts her head when I'm completely done.
<</InformationUiPopUp>>
<video src="assets/img/story/character/housematefemale/3/08.mp4"/>
<<TalkNPC _npc "Better?">>
<<TalkMC "Much better.">>
<<TalkNPC _npc "That's what I'm here for.">>
<<InformationUiPopUp>>She wipes the corner of her mouth with her thumb, then crawls back up and lies down beside me, pressing herself against my side with her head resting on my shoulder. The warm afternoon sun holds steady above the garden.
<</InformationUiPopUp>>
<<TalkMC "You've changed.">>
<<TalkNPC _npc "Maybe I just figured out what I want.">>
<<TalkMC "And what's that?">>
<<TalkNPC _npc "To make you feel good. Is that so complicated?">>
<<TalkMC "Not at all.">>
<<TalkNPC _npc "Then stop overthinking it and enjoy the afternoon.">>
<<InformationUiPopUp>>She stays pressed against me, relaxed and content, one hand resting flat on my chest. My power did its job once again, but something about the way she's lying here against me makes me wonder if there was already something there to work with. The garden is warm and still around us.
<</InformationUiPopUp>><</revealtext>>
/* ====================================================
*
* ----------------------------------- CHAPTER 5 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 4>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><</if>>
<<passagebg>><<sound "bg" "bg.empty" true>><img src="assets/img/misc/home/bathroom/bathroom.webp"/><</passagebg>>
<<InformationUiPopUp>>Morning. I push open the bathroom door without thinking, the same way I did the very first time, except nothing about this moment resembles that one. <<print _npc.name>> is already inside, under the warm spray of the shower, the curtain open. She turns her head when she hears me, and instead of anger, she smiles, slow and easy, and keeps washing herself without a word.
<</InformationUiPopUp>>
<video src="assets/img/story/character/housematefemale/4/01.mp4"/>
<<TalkNPC _npc "You're right on time.">>
<<TalkMC "Was I expected?">>
<<TalkNPC _npc "I was hoping.">>
<<InformationUiPopUp>>She holds my gaze as she runs her hands slowly across her body, deliberate, unhurried, fully comfortable being watched. She makes no move to cover herself, no hesitation. She wants me watching and makes no effort to pretend otherwise.
<</InformationUiPopUp>>
<video src="assets/img/story/character/housematefemale/4/02.mp4"/>
<<TalkMC "Come here.">>
<<TalkNPC _npc "Yes.">>
<<InformationUiPopUp>>She's still under the shower, wet and warm, soap still lathered on her skin. I reach out and take her breasts in both hands, squeezing firmly. She exhales sharply, her eyes closing for just a moment before she looks back up at me.
<</InformationUiPopUp>>
<video src="assets/img/story/character/housematefemale/4/03.mp4"/>
<<TalkNPC _npc "I've been thinking about you since I woke up.">>
<<TalkMC "Show me.">>
<<TalkNPC _npc "With pleasure.">>
<<InformationUiPopUp>>She drops to her knees immediately, her wet hands finding my waistband, pulling my pants and underwear down in one motion without hesitation.
<</InformationUiPopUp>>
<video src="assets/img/story/character/housematefemale/4/04.mp4"/>
<<InformationUiPopUp>>She wraps both hands around me, strokes once, then takes me into her mouth hard and deep from the very start, no slow build, no hesitation. Her eyes stay fixed on mine.
<</InformationUiPopUp>>
<video src="assets/img/story/character/housematefemale/4/05.mp4"/>
<<TalkMC "Deeper.">>
<<TalkNPC _npc "Mmh...">>
<<InformationUiPopUp>>She pushes herself further without pulling back once, both hands gripping my thighs, taking me as deep as she can, gagging slightly and not stopping for it. Her pace is relentless, the sound of the shower in the background, her own sounds mixing with the steam filling the room.
<</InformationUiPopUp>>
<<TalkNPC _npc "Glrk... ghlk... mmh...">>
<video src="assets/img/story/character/housematefemale/4/06.mp4"/>
<<TalkMC "Don't stop.">>
<<TalkNPC _npc "Never.">>
<<InformationUiPopUp>>She works with total focus, reading every reaction, adjusting every time my grip tightens in her hair, pushing harder each time. I pull her off before I finish.
<</InformationUiPopUp>>
<video src="assets/img/story/character/housematefemale/4/07.mp4"/>
<<InformationUiPopUp>>Seeing her like that, naked and on her knees in front of me, sucking me without holding back, gives me only one desire: to go even further.
<</InformationUiPopUp>>
<<revealtext "chapter5">><<InformationUiPopUp "Psychic Power" #7aa2ff>>You decide to use your power on <<=_npc.name>>.<<if _npc.replaytalk == false>>
<em>-1 Psychic Power</em><</if>>
<</InformationUiPopUp>>
<<TalkMC "Listen to my order.">>
<<InformationUiPopUp>>I lower my voice, eyes locked on hers.
<</InformationUiPopUp>>
<<TalkMC "You're going to want to go further with me. You're going to love it, and you're going to want more.">>
<<InformationUiPopUp>>Three seconds of silence. Only the sound of the shower remains. Then she comes back, her eyes fixing on my cock, one hand sliding instinctively between her thighs and starting to touch herself.
<</InformationUiPopUp>>
<<TalkMC "Get on top of me. Now.">>
<<TalkNPC _npc "Yes.">>
<<InformationUiPopUp>>I lie back on the bathroom floor and she swings one leg over immediately, straddling my hips, reaching down to position me and sinking down onto me in one slow, deliberate motion. She lets out a long breath as she bottoms out, then begins to move, her hips rolling back and forth with controlled intensity.
<</InformationUiPopUp>>
<video src="assets/img/story/character/housematefemale/4/08.mp4"/>
<<TalkNPC _npc "Fuck, you feel so good.">>
<<TalkMC "Keep going.">>
<<TalkNPC _npc "I'm not stopping.">>
<<InformationUiPopUp>>She picks up the pace, hands flat on my chest for leverage, moving harder, her breathing becoming ragged. Her movements grow increasingly intense, chasing her own release while keeping her eyes locked onto mine.
<</InformationUiPopUp>>
<video src="assets/img/story/character/housematefemale/4/09.mp4"/>
<<TalkMC "Come for me.">>
<<TalkNPC _npc "Yes, yes, I'm...">>
<<InformationUiPopUp>>She cries out and shudders, her hips grinding down hard as she comes, her whole body tensing and releasing above me. She stays there for a moment, catching her breath, then looks down at me with dark, wanting eyes.
<</InformationUiPopUp>>
<video src="assets/img/story/character/housematefemale/4/10.mp4"/>
<<TalkNPC _npc "I want more.">>
<<TalkMC "Turn around.">>
<<TalkNPC _npc "Yes.">>
<<InformationUiPopUp>>She climbs off and gets on her hands and knees on the bathroom floor without needing to be asked twice, offering herself immediately. I move behind her and push inside without preamble. She lets out a sharp breath and drops her head.
<</InformationUiPopUp>>
<video src="assets/img/story/character/housematefemale/4/11.mp4"/>
<<TalkMC "Don't move.">>
<<TalkNPC _npc "Please, don't stop.">>
<<InformationUiPopUp>>I set a hard, driving pace and she takes it fully, her hands pressed flat against the floor tiles, bracing. Every thrust pushes a sound out of her she doesn't try to suppress.
<</InformationUiPopUp>>
<video src="assets/img/story/character/housematefemale/4/12.mp4"/>
<<TalkNPC _npc "Harder.">>
<<TalkMC "You want more?">>
<<TalkNPC _npc "Yes, please, harder.">>
<<InformationUiPopUp>>I grip her hips and drive harder, exactly as she asked. She presses back against every thrust, matching the pace, completely given over to it.
<</InformationUiPopUp>>
<video src="assets/img/story/character/housematefemale/4/13.mp4"/>
<<TalkMC "On your knees. Swallow everything, not a single drop.">>
<<TalkNPC _npc "Yes.">>
<<InformationUiPopUp>>She turns and drops back to her knees in front of me instantly, mouth already open before I reach her. She takes me in deep, one hand wrapped around the base, the other gripping my thigh, working with total urgency now, chasing my finish with everything she has.
<</InformationUiPopUp>>
<video src="assets/img/story/character/housematefemale/4/14.mp4"/>
<<TalkMC "I'm going to come.">>
<<TalkNPC _npc "Give it to me.">>
<<InformationUiPopUp>>I finish hard into her mouth. She takes everything without pulling back, swallows without hesitation, holding eye contact all the way through until I'm completely done. She stays on her knees for a moment after, composed, looking up at me with quiet satisfaction.
<</InformationUiPopUp>>
<<TalkNPC _npc "Good morning.">>
<<TalkMC "Good morning.">>
<<InformationUiPopUp>>The shower is still running. Steam drifts through the bathroom. She rises slowly from her knees and steps back under the warm water without another word, calm and content, like this is simply how mornings are now.
<</InformationUiPopUp>><</revealtext>>
/* ====================================================
*
* ----------------------------------- CHAPTER 6 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 5>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><</if>>
<<passagebg>><<sound "bg" "bg.empty" true>><img src="assets/img/misc/home/housematefemalebedroomnight.webp"/><</passagebg>>
<<InformationUiPopUp>>It's night. I push open the door to <<print _npc.name>>'s room and find her exactly where I knew she would be, sitting on the edge of the bed, hands folded in her lap, eyes on me the moment the door opens. She was waiting. She doesn't pretend otherwise.
<</InformationUiPopUp>>
<<TalkNPC _npc "I was hoping you'd come.">>
<<TalkMC "I know.">>
<<InformationUiPopUp>>I've reached the end. There's only one last order left to plant in her before she's completely mine.
<</InformationUiPopUp>>
<<revealtext "chapter6">><<InformationUiPopUp "Psychic Power" #7aa2ff>>You decide to use your power on <<=_npc.name>>.<<if _npc.replaytalk == false>>
<em>-1 Psychic Power</em><</if>>
<</InformationUiPopUp>>
<<TalkMC "Listen to my order.">>
<<TalkMC "From now on, you will call me Master. You will become my object, you will belong to me and me alone. And you will be happy that way.">>
<<InformationUiPopUp>>I wait. A few seconds, enough time for the order to take root in her. Then she comes back, and when her eyes settle on me, there's nothing left of the old resistance. Nothing at all.
<</InformationUiPopUp>>
<<TalkNPC _npc "...">>
<<TalkNPC _npc "Master... what can I do for you?">>
<<InformationUiPopUp>>I walk to her and take her face in one hand, tilting it up. She leans into it instantly, like that's where her cheek was always meant to rest. I lean down and kiss her, hard and deep, and she opens immediately, her hands gripping the edge of the bed to stay steady.
<</InformationUiPopUp>>
<video src="assets/img/story/character/housematefemale/5/01.mp4"/>
<<TalkMC "On the floor.">>
<<TalkNPC _npc "Yes, Master.">>
<<InformationUiPopUp>>She slides off the bed and sits on the floor, back against the mattress, eyes lifted toward me, dark and completely open. I step forward and take hold of her head with one hand.
<</InformationUiPopUp>>
<video src="assets/img/story/character/housematefemale/5/02.mp4"/>
<<TalkMC "Take it.">>
<<TalkNPC _npc "Glrk... ghlk... mmh...">>
<<InformationUiPopUp>>She takes everything I give her, hands flat on the floor at her sides, letting me control the depth and pace entirely. When I pull back she catches her breath, eyes watering, and looks straight back up at me without looking away.
<</InformationUiPopUp>>
<<TalkNPC _npc "More, Master. Please.">>
<<TalkMC "Spread your legs.">>
<<TalkNPC _npc "Yes.">>
<<InformationUiPopUp>>I reach down and push her thighs apart, sliding my fingers against her. She is already completely soaked.
<</InformationUiPopUp>>
<video src="assets/img/story/character/housematefemale/5/03.mp4"/>
<<TalkNPC _npc "Master, please, I need you inside me.">>
<<TalkMC "On the bed.">>
<<TalkNPC _npc "Yes, Master.">>
<<InformationUiPopUp>>She climbs onto the bed and lies back, legs already parting. I push inside her in one firm motion and she cries out, hands grabbing the sheets.
<</InformationUiPopUp>>
<video src="assets/img/story/character/housematefemale/5/04.mp4"/>
<<TalkMC "Look at me.">>
<<TalkNPC _npc "Yes, Master, I'm looking, please don't stop.">>
<<InformationUiPopUp>>I drive harder, watching her come apart beneath me, her body completely open and given over.
<</InformationUiPopUp>>
<video src="assets/img/story/character/housematefemale/5/05.mp4"/>
<<TalkMC "Floor. Hands and knees.">>
<<TalkNPC _npc "Yes, Master.">>
<<InformationUiPopUp>>She rolls off the bed and drops onto her hands and knees on the floor instantly. I move behind her and push back inside without pause. She drops her head and groans.
<</InformationUiPopUp>>
<video src="assets/img/story/character/housematefemale/5/06.mp4"/>
<<TalkNPC _npc "Harder, Master, please.">>
<<TalkMC "You want more?">>
<<TalkNPC _npc "Yes, please, yes.">>
<<InformationUiPopUp>>I grip her hips and give her exactly that, relentless and deep. She presses back against every thrust, completely overwhelmed.
<</InformationUiPopUp>>
<video src="assets/img/story/character/housematefemale/5/07.mp4"/>
<<TalkMC "On top. Now.">>
<<TalkNPC _npc "Yes, Master.">>
<<InformationUiPopUp>>I lie back on the floor and she straddles me immediately, reaching down to guide me inside her, then sinking all the way down with a broken exhale. She begins to move, slow at first, then building fast.
<</InformationUiPopUp>>
<video src="assets/img/story/character/housematefemale/5/08.mp4"/>
<<TalkNPC _npc "You go so deep, Master.">>
<<TalkMC "On the bed. Same position as before.">>
<<TalkNPC _npc "Yes, Master.">>
<<InformationUiPopUp>>She climbs off and gets onto the bed, positioning herself on her hands and knees at the edge of the mattress. I move behind her and push inside again, taking hold of her hips.
<</InformationUiPopUp>>
<video src="assets/img/story/character/housematefemale/5/09.mp4"/>
<<TalkMC "Don't move.">>
<<TalkNPC _npc "Yes, Master, I won't move.">>
<<InformationUiPopUp>>I set a brutal pace, holding her in place. She takes every thrust without pulling away, her voice breaking on each one.
<</InformationUiPopUp>>
<video src="assets/img/story/character/housematefemale/5/10.mp4"/>
<<TalkMC "On your back. Legs up. Wide.">>
<<TalkNPC _npc "Yes, Master.">>
<<InformationUiPopUp>>I lie flat on the bed and she swings over me into a full split, thighs spread wide on either side, sinking down slowly onto me with a long, shaking exhale.
<</InformationUiPopUp>>
<video src="assets/img/story/character/housematefemale/5/11.mp4"/>
<<TalkNPC _npc "Master, it's so deep like this.">>
<<TalkMC "Keep going.">>
<<TalkNPC _npc "Yes, Master.">>
<<InformationUiPopUp>>She rides in long, grinding strokes, the full split holding her completely open, her body trembling under the effort and the intensity.
<</InformationUiPopUp>>
<video src="assets/img/story/character/housematefemale/5/12.mp4"/>
<<TalkMC "On your back. Legs against your chest.">>
<<TalkNPC _npc "Yes, Master, anything you want.">>
<<InformationUiPopUp>>She rolls onto her back and pulls her legs high against her own chest, holding them there, completely open. I push inside and begin fucking her in long, deep strokes.
<</InformationUiPopUp>>
<video src="assets/img/story/character/housematefemale/5/13.mp4"/>
<<TalkNPC _npc "Master, it feels so good, please don't stop.">>
<<TalkMC "Stay open.">>
<<TalkNPC _npc "Yes, yes, I will.">>
<<InformationUiPopUp>>I drive deeper, watching her face completely unravel. She keeps her legs pulled up obediently, giving me everything.
<</InformationUiPopUp>>
<video src="assets/img/story/character/housematefemale/5/14.mp4"/>
<video src="assets/img/story/character/housematefemale/5/15.mp4"/>
<<TalkMC "Faster now.">>
<<TalkNPC _npc "Master, I'm going to... I can't... please.">>
<<TalkMC "Come for me.">>
<<TalkNPC _npc "Master, Master, I'm coming.">>
<<InformationUiPopUp>>I push faster, harder, and she starts to shake, legs trembling in her own grip, her whole body tensing toward breaking point.
<</InformationUiPopUp>>
<video src="assets/img/story/character/housematefemale/5/16.mp4"/>
<video src="assets/img/story/character/housematefemale/5/17.mp4"/>
<<InformationUiPopUp>>She comes apart completely, legs shaking uncontrollably, crying out in long broken waves. I don't stop, driving through her orgasm, keeping her there.
<</InformationUiPopUp>>
<video src="assets/img/story/character/housematefemale/5/18.mp4"/>
<<TalkMC "To the edge of the bed.">>
<<TalkNPC _npc "Yes, Master.">>
<<InformationUiPopUp>>Still trembling, she shifts herself to the very edge of the bed, legs still held up. I grip her thighs and continue from there, the angle even deeper from the edge.
<</InformationUiPopUp>>
<video src="assets/img/story/character/housematefemale/5/19.mp4"/>
<<TalkNPC _npc "Master, I'm still coming, it's too much.">>
<<TalkMC "Take it.">>
<<TalkNPC _npc "Yes, Master.">>
<<InformationUiPopUp>>I hold the pace, deep and relentless, feeling the finish building hard. I don't pull back.
<</InformationUiPopUp>>
<video src="assets/img/story/character/housematefemale/5/20.mp4"/>
<<TalkMC "I'm going to fill you.">>
<<TalkNPC _npc "Please, Master, please, fill me.">>
<<InformationUiPopUp>>I finish deep inside her, grinding through it, continuing to thrust as I come, burying it as deep as possible.
<</InformationUiPopUp>>
<video src="assets/img/story/character/housematefemale/5/21.mp4"/>
<video src="assets/img/story/character/housematefemale/5/22.mp4"/>
<<TalkNPC _npc "Thank you, Master.">>
<<TalkMC "Good girl.">>
<<InformationUiPopUp>>I stay there for a moment, completely still, before slowly pulling back. She stays exactly where she is, legs finally lowered, eyes half closed, chest rising and falling. Completely spent. Completely content. She looks up at me with an expression that holds nothing back.
<</InformationUiPopUp>>
<<TalkNPC _npc "I'm yours, Master. Always.">>
<<InformationUiPopUp>>The room is warm and silent around us. She doesn't move. She doesn't need to.
It's done. She's mine, completely, irreversibly. My power has done what it exists to do.
<</InformationUiPopUp>><</revealtext>>
/* ====================================================
*
* -------------------------------- REPLAY CHAPTER --------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl > 5>><<set $SaveTalklvl = _npc.talklvl>><<set _npc.replaytalk = true>><<set _gotoReplayNpc = "Talk." + _npc.id>>
<<passagebg>><img src="assets/background.gif"/><</passagebg>>
<style>.rCard a{display:flex;align-items:center;gap:clamp(6px,1vw,10px);padding:clamp(8px,1.2vw,11px) clamp(10px,1.5vw,16px);border-radius:10px;background:rgba(230,87,99,.07);border:1px solid rgba(230,87,99,.18);text-decoration:none;transition:background .15s;}.rCard a:hover{background:rgba(230,87,99,.14);border-color:rgba(230,87,99,.35);}.rCard .rNum{font-size:calc(clamp(14px,1.8vw,18px) + var(--font-boost,0px));font-weight:950;color:rgba(255,255,255,.92);}.rCard .rLabel{font-size:calc(clamp(9px,1vw,12px) + var(--font-boost,0px));font-weight:900;letter-spacing:.16em;text-transform:uppercase;color:rgba(230,87,99,.55);}.rCard .rArrow{margin-left:auto;font-size:calc(clamp(9px,1vw,12px) + var(--font-boost,0px));font-weight:900;letter-spacing:.1em;color:rgba(230,87,99,.45);}</style><div style="display:flex;flex-direction:column;gap:6px;width:100%;margin-top:6px;"><div style="font-size:calc(clamp(9px,1vw,12px) + var(--font-boost,0px));font-weight:900;letter-spacing:.16em;text-transform:uppercase;color:rgba(255,255,255,.18);margin-bottom:6px;text-align:center;">— Select a scene to replay —</div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>01</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 0>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>02</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 1>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>03</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 2>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>04</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 3>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>05</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 4>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>06</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 5>><<goto _gotoReplayNpc>><</link>></div></div>
<</if>><</if>><div class="BottomUiBarCustom">
<<if _npc.talklvl == 0>><<BottomButton "Decision">><<revealbtn "chapter1" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 1>><<BottomButton "Decision">><<revealbtn "chapter2" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 2>><<BottomButton "Decision">><<revealbtn "chapter3Dare" "💬 Dare" "" "ch3tod" "ch3dare" true>><</revealbtn>><<revealbtn "chapter3Truth" "💬 Truth" "" "ch3tod" "ch3truth" true>><</revealbtn>><<if $Fitness >= 25>><<revealbtn "chapter3DareYes" "💬 Yes" "" "ch3dare" "ch3next" false>><</revealbtn>><<else>><<revealbtn "" "🔒 Not enough Fitness" "" "ch3dare" "" false>><</revealbtn>><</if>><<revealbtn "chapter3DareJoker" "🃏 Joker" "" "ch3dare" "ch3next" false>><</revealbtn>><<revealbtn "chapter3TruthYes" "💬 Yes" "" "ch3truth" "ch3next" false>><</revealbtn>><<revealbtn "chapter3TruthJoker" "🃏 Joker" "" "ch3truth" "ch3next" false>><</revealbtn>><<revealbtn "chapter3ToD" "💬 Truth or Dare ?" "" "ch3next" "ch3power" false>><</revealbtn>><<revealbtn "chapter3" "🧠 Use power" "moveBtn" "ch3power" "" false>><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 3>><<BottomButton "Decision">><<revealbtn "chapter4" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 4>><<BottomButton "Decision">><<revealbtn "chapter5" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 5>><<BottomButton "Decision">><<revealbtn "chapter6" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><</if>>
<<BottomButton "Move" "moveBtn">><<if $FromOtherPlace == true>><<link "↩️ Return">><<if _npc.replaytalk == false>><<set _npc.talklvl++>><<set _npc.lvl++>><<set $PsychicPower -= 1>><<if _NextTime == true>><<set $Time++>><<set _NextTime = false>><</if>><<else>><<set _npc.talklvl = $SaveTalklvl>><<set _npc.replaytalk = false>><</if>><<ReturnToGoto>><<set $FromOtherPlace = false>><</link>><<else>><<link "↩️ Return">><<if _npc.replaytalk == false>><<set _npc.talklvl++>><<set _npc.lvl++>><<set $PsychicPower -= 1>><<if _NextTime == true>><<set $Time++>><<set _NextTime = false>><</if>><<else>><<set _npc.talklvl = $SaveTalklvl>><<set _npc.replaytalk = false>><</if>><<bgpause>><<goto _gotoNpc>><</link>><</if>><</BottomButton>>
</div><<sound "music" "music.music" true>><<set _raw = $ActiveNPC>><<if !_raw or _raw.id is undefined>>Invalid NPC.<<else>><<set _id = String(_raw.id)>><<set _key = "NPC" + _id>><<run State.temporary.npcObj = State.variables[State.temporary.key] || State.variables[_key]>><<set _npc = _npcObj>><<set _gotoNpc = _npc.id + ".interact">>
/* ====================================================
*
* ----------------------------------- CHAPTER 1 -----------------------------------------
*
*/ ====================================================
<<if _npc.talklvl == 0>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><</if>>
<<passagebg>><img src="assets/img/misc/???.png"/><</passagebg>>
<<InformationUiPopUp>>
<</InformationUiPopUp>>
<<TalkMC "">>
<<TalkNPC _npc "">>
/* ====================================================
*
* ----------------------------------- CHAPTER 2 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 1>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><</if>>
<<passagebg>><img src="assets/img/misc/???.png"/><</passagebg>>
<<InformationUiPopUp>>
<</InformationUiPopUp>>
<<TalkMC "">>
<<TalkNPC _npc "">>
/* ====================================================
*
* ----------------------------------- CHAPTER 3 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 2>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><</if>>
<<passagebg>><img src="assets/img/misc/???.png"/><</passagebg>>
<<InformationUiPopUp>>
<</InformationUiPopUp>>
<<TalkMC "">>
<<TalkNPC _npc "">>
/* ====================================================
*
* ----------------------------------- CHAPTER 4 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 3>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><</if>>
<<passagebg>><img src="assets/img/misc/???.png"/><</passagebg>>
<<InformationUiPopUp>>
<</InformationUiPopUp>>
<<TalkMC "">>
<<TalkNPC _npc "">>
/* ====================================================
*
* ----------------------------------- CHAPTER 5 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 4>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><</if>>
<<passagebg>><img src="assets/img/misc/???.png"/><</passagebg>>
<<InformationUiPopUp>>
<</InformationUiPopUp>>
<<TalkMC "">>
<<TalkNPC _npc "">>
/* ====================================================
*
* ----------------------------------- CHAPTER 6 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 5>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><</if>>
<<passagebg>><img src="assets/img/misc/???.png"/><</passagebg>>
<<InformationUiPopUp>>
<</InformationUiPopUp>>
<<TalkMC "">>
<<TalkNPC _npc "">>
/* ====================================================
*
* -------------------------------- REPLAY CHAPTER --------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl > 5>><<set $SaveTalklvl = _npc.talklvl>><<set _npc.replaytalk = true>><<set _gotoReplayNpc = "Talk." + _npc.id>>
<<passagebg>><img src="assets/background.gif"/><</passagebg>>
<style>.rCard a{display:flex;align-items:center;gap:clamp(6px,1vw,10px);padding:clamp(8px,1.2vw,11px) clamp(10px,1.5vw,16px);border-radius:10px;background:rgba(230,87,99,.07);border:1px solid rgba(230,87,99,.18);text-decoration:none;transition:background .15s;}.rCard a:hover{background:rgba(230,87,99,.14);border-color:rgba(230,87,99,.35);}.rCard .rNum{font-size:calc(clamp(14px,1.8vw,18px) + var(--font-boost,0px));font-weight:950;color:rgba(255,255,255,.92);}.rCard .rLabel{font-size:calc(clamp(9px,1vw,12px) + var(--font-boost,0px));font-weight:900;letter-spacing:.16em;text-transform:uppercase;color:rgba(230,87,99,.55);}.rCard .rArrow{margin-left:auto;font-size:calc(clamp(9px,1vw,12px) + var(--font-boost,0px));font-weight:900;letter-spacing:.1em;color:rgba(230,87,99,.45);}</style><div style="display:flex;flex-direction:column;gap:6px;width:100%;margin-top:6px;"><div style="font-size:calc(clamp(9px,1vw,12px) + var(--font-boost,0px));font-weight:900;letter-spacing:.16em;text-transform:uppercase;color:rgba(255,255,255,.18);margin-bottom:6px;text-align:center;">— Select a scene to replay —</div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>01</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 0>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>02</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 1>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>03</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 2>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>04</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 3>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>05</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 4>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>06</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 5>><<goto _gotoReplayNpc>><</link>></div></div>
<</if>><</if>><div class="BottomUiBarCustom">
<<if _npc.talklvl == 0>><<BottomButton "Decision">><<revealbtn "chapter1" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 1>><<BottomButton "Decision">><<revealbtn "chapter2" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 2>><<BottomButton "Decision">><<revealbtn "chapter3" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 3>><<BottomButton "Decision">><<revealbtn "chapter4" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 4>><<BottomButton "Decision">><<revealbtn "chapter5" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 5>><<BottomButton "Decision">><<revealbtn "chapter6" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><</if>>
<<BottomButton "Move" "moveBtn">><<if $FromOtherPlace == true>><<link "↩️ Return">><<if _npc.replaytalk == false>><<set _npc.talklvl++>><<set _npc.lvl++>><<set $PsychicPower -= 1>><<if _NextTime == true>><<set $Time++>><<set _NextTime = false>><</if>><<else>><<set _npc.talklvl = $SaveTalklvl>><<set _npc.replaytalk = false>><</if>><<ReturnToGoto>><<set $FromOtherPlace = false>><</link>><<else>><<link "↩️ Return">><<if _npc.replaytalk == false>><<set _npc.talklvl++>><<set _npc.lvl++>><<set $PsychicPower -= 1>><<if _NextTime == true>><<set $Time++>><<set _NextTime = false>><</if>><<else>><<set _npc.talklvl = $SaveTalklvl>><<set _npc.replaytalk = false>><</if>><<bgpause>><<goto _gotoNpc>><</link>><</if>><</BottomButton>>
</div><<sound "music" "music.music" true>><<set _raw = $ActiveNPC>><<if !_raw or _raw.id is undefined>>Invalid NPC.<<else>><<set _id = String(_raw.id)>><<set _key = "NPC" + _id>><<run State.temporary.npcObj = State.variables[State.temporary.key] || State.variables[_key]>><<set _npc = _npcObj>><<set _gotoNpc = _npc.id + ".interact">>
/* ====================================================
*
* ----------------------------------- CHAPTER 1 -----------------------------------------
*
*/ ====================================================
<<if _npc.talklvl == 0>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><</if>>
<<passagebg>><img src="assets/img/misc/???.png"/><</passagebg>>
<<InformationUiPopUp>>
<</InformationUiPopUp>>
<<TalkMC "">>
<<TalkNPC _npc "">>
/* ====================================================
*
* ----------------------------------- CHAPTER 2 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 1>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><</if>>
<<passagebg>><img src="assets/img/misc/???.png"/><</passagebg>>
<<InformationUiPopUp>>
<</InformationUiPopUp>>
<<TalkMC "">>
<<TalkNPC _npc "">>
/* ====================================================
*
* ----------------------------------- CHAPTER 3 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 2>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><</if>>
<<passagebg>><img src="assets/img/misc/???.png"/><</passagebg>>
<<InformationUiPopUp>>
<</InformationUiPopUp>>
<<TalkMC "">>
<<TalkNPC _npc "">>
/* ====================================================
*
* ----------------------------------- CHAPTER 4 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 3>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><</if>>
<<passagebg>><img src="assets/img/misc/???.png"/><</passagebg>>
<<InformationUiPopUp>>
<</InformationUiPopUp>>
<<TalkMC "">>
<<TalkNPC _npc "">>
/* ====================================================
*
* ----------------------------------- CHAPTER 5 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 4>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><</if>>
<<passagebg>><img src="assets/img/misc/???.png"/><</passagebg>>
<<InformationUiPopUp>>
<</InformationUiPopUp>>
<<TalkMC "">>
<<TalkNPC _npc "">>
/* ====================================================
*
* ----------------------------------- CHAPTER 6 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 5>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><</if>>
<<passagebg>><img src="assets/img/misc/???.png"/><</passagebg>>
<<InformationUiPopUp>>
<</InformationUiPopUp>>
<<TalkMC "">>
<<TalkNPC _npc "">>
/* ====================================================
*
* -------------------------------- REPLAY CHAPTER --------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl > 5>><<set $SaveTalklvl = _npc.talklvl>><<set _npc.replaytalk = true>><<set _gotoReplayNpc = "Talk." + _npc.id>>
<<passagebg>><img src="assets/background.gif"/><</passagebg>>
<style>.rCard a{display:flex;align-items:center;gap:clamp(6px,1vw,10px);padding:clamp(8px,1.2vw,11px) clamp(10px,1.5vw,16px);border-radius:10px;background:rgba(230,87,99,.07);border:1px solid rgba(230,87,99,.18);text-decoration:none;transition:background .15s;}.rCard a:hover{background:rgba(230,87,99,.14);border-color:rgba(230,87,99,.35);}.rCard .rNum{font-size:calc(clamp(14px,1.8vw,18px) + var(--font-boost,0px));font-weight:950;color:rgba(255,255,255,.92);}.rCard .rLabel{font-size:calc(clamp(9px,1vw,12px) + var(--font-boost,0px));font-weight:900;letter-spacing:.16em;text-transform:uppercase;color:rgba(230,87,99,.55);}.rCard .rArrow{margin-left:auto;font-size:calc(clamp(9px,1vw,12px) + var(--font-boost,0px));font-weight:900;letter-spacing:.1em;color:rgba(230,87,99,.45);}</style><div style="display:flex;flex-direction:column;gap:6px;width:100%;margin-top:6px;"><div style="font-size:calc(clamp(9px,1vw,12px) + var(--font-boost,0px));font-weight:900;letter-spacing:.16em;text-transform:uppercase;color:rgba(255,255,255,.18);margin-bottom:6px;text-align:center;">— Select a scene to replay —</div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>01</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 0>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>02</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 1>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>03</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 2>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>04</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 3>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>05</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 4>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>06</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 5>><<goto _gotoReplayNpc>><</link>></div></div>
<</if>><</if>><div class="BottomUiBarCustom">
<<if _npc.talklvl == 0>><<BottomButton "Decision">><<revealbtn "chapter1" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 1>><<BottomButton "Decision">><<revealbtn "chapter2" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 2>><<BottomButton "Decision">><<revealbtn "chapter3" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 3>><<BottomButton "Decision">><<revealbtn "chapter4" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 4>><<BottomButton "Decision">><<revealbtn "chapter5" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 5>><<BottomButton "Decision">><<revealbtn "chapter6" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><</if>>
<<BottomButton "Move" "moveBtn">><<if $FromOtherPlace == true>><<link "↩️ Return">><<if _npc.replaytalk == false>><<set _npc.talklvl++>><<set _npc.lvl++>><<set $PsychicPower -= 1>><<if _NextTime == true>><<set $Time++>><<set _NextTime = false>><</if>><<else>><<set _npc.talklvl = $SaveTalklvl>><<set _npc.replaytalk = false>><</if>><<ReturnToGoto>><<set $FromOtherPlace = false>><</link>><<else>><<link "↩️ Return">><<if _npc.replaytalk == false>><<set _npc.talklvl++>><<set _npc.lvl++>><<set $PsychicPower -= 1>><<if _NextTime == true>><<set $Time++>><<set _NextTime = false>><</if>><<else>><<set _npc.talklvl = $SaveTalklvl>><<set _npc.replaytalk = false>><</if>><<bgpause>><<goto _gotoNpc>><</link>><</if>><</BottomButton>>
</div><style>Unveiled Desire</style><<sound "music" "music.music" true>><<passagebg>><<if $Time !== 3>><<sound "bg" "bg.classroom" true>><img src="assets/img/misc/university/class1.webp"/><<else>><<sound "bg" "bg.empty" true>><img src="assets/img/misc/university/class1night.webp"/><</if>><</passagebg>>
<<if $Time == 0>><<Interact $NPCTeachTech>>
<<Interact $NPCBestFriend>>
<<Interact $NPCMate2>>
<<Interact $NPCMate3>><<elseif $Time == 1>><<Interact $NPCTeachTech>><<else>><<InformationUiPopUp "Interact">>There is no one.<</InformationUiPopUp>><</if>>
<<imgcorruption university>>
<div class="BottomUiBarCustom">
<<BottomButton "Move">>[[🚪 Exit|University]]<</BottomButton>>
</div><<sound "music" "music.music" true>><<sound "bg" "bg.empty" true>><<passagebg>><<if $Time !== 3>><img src="assets/img/misc/university/staffroom.webp"/><<else>><img src="assets/img/misc/university/staffroomnight.webp"/><</if>><</passagebg>>
<<if $Time == 0>><<Interact $NPCTeachSport>><<elseif $Time == 2>><<Interact $NPCTeachLang>><br><<Interact $NPCTeachTech>><<else>><<InformationUiPopUp "Interact">>There is no one.<</InformationUiPopUp>><</if>>
<div class="BottomUiBarCustom"><<if $NPCBestFriend.lvl == 4 && $TalkBestFriendChapter5 == false>><<BottomButton "Action">><<if $PsychicPower <= 0>><<link "🔒 Not enough Psychic Power">><</link>><<else>><<link "💬 Talk with <<print $NPCTeachLang.name>>">><<goto "Talk.BestFriend.Chapter5">><</link>><</if>><</BottomButton>><</if>>
<<BottomButton "Move">>[[🖥️ My Personal Office|UniversityPersonalOffice]]
[[🚪 Exit|University]]<</BottomButton>>
</div><<sound "music" "music.music" true>><<sound "bg" "bg.empty" true>><<passagebg>><<if $Time !== 3>><img src="assets/img/misc/university/principaloffice.webp"/><<else>><img src="assets/img/misc/university/principalofficenight.webp"/><</if>><</passagebg>>
<<if $Time !== 3>><<Interact $NPCPrincipal>><<else>><<InformationUiPopUp "Interact">>There is no one.<</InformationUiPopUp>><</if>>
<div class="BottomUiBarCustom"><<if $UniversityHiring == true>><br><<BottomButton "Action">><<link "💬 Take the interview">><<goto "UniversityWork3">><</link>><</BottomButton>><</if>>
<<BottomButton "Move">>[[🚪 Exit|University]]<</BottomButton>>
</div><<sound "music" "music.music" true>><<sound "bg" "bg.empty" true>><<passagebg>><<if $Time !== 3>><img src="assets/img/misc/city/cityhall/mayoroffice.webp"/><<else>><img src="assets/img/misc/city/cityhall/mayorofficenight.webp"/><</if>><</passagebg>>
<<if $Time !== 3>><<Interact $NPCMayor>><<else>><<InformationUiPopUp "Interact">>There is no one.<</InformationUiPopUp>><</if>>
<div class="BottomUiBarCustom"><<if $NPCMayor.lvl == 4 and $MayorStoryInfo10 == true and $MayorStoryInfo11 == false>><br><<BottomButton "Story">><<link "💬 Talk about Hargrove">><<goto "MayorStory19">><</link>><</BottomButton>><</if>>
<<BottomButton "Move">>[[🚪 Exit|CityHall]]<</BottomButton>>
</div><<sound "music" "music.music" true>><<sound "bg" "bg.empty" true>><<passagebg>><<if $Time !== 3>><img src="assets/img/misc/city/cityhall/meetingroom.webp"/><<else>><img src="assets/img/misc/city/cityhall/meetingroomnight.webp"/><</if>><</passagebg>><div class="laws-wrap"><div class="laws-header"><div class="laws-title">⚖️ City Laws</div><div class="laws-sub">Pass laws to corrupt the city and unlock new interactions. Each law requires enough Reputation and the Mayor's trust.</div></div><div class="laws-progress"><div class="laws-progress-label">City Corruption Level</div><div class="laws-progress-track"><div class="laws-progress-fill" id="lawsProgressFill" style="width:0%"></div></div><div class="laws-progress-val" id="lawsProgressVal"><<= $Corruption.city >> / 5</div></div><div class="laws-list" id="lawsList"></div></div>
<style>
.laws-wrap{width:100%;max-width:860px;margin:0 auto;font-family:inherit;padding:0 4px;}
.laws-header{padding:0 0 14px 0;border-bottom:1px solid rgba(255,255,255,.07);margin-bottom:18px;}
.laws-title{font-size:calc(20px + var(--font-boost,0px));font-weight:950;color:rgba(255,255,255,.95);letter-spacing:-.01em;margin-bottom:8px;}
.laws-sub{font-size:calc(14px + var(--font-boost,0px));font-weight:600;color:rgba(255,255,255,.55);line-height:1.55;}
.laws-progress{display:flex;align-items:center;gap:12px;margin-bottom:18px;padding:12px 16px;border-radius:10px;background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.07);flex-wrap:wrap;}
.laws-progress-label{font-size:calc(14px + var(--font-boost,0px));font-weight:800;letter-spacing:.08em;color:rgba(255,255,255,.50);text-transform:uppercase;white-space:nowrap;}
.laws-progress-track{flex:1;min-width:80px;height:5px;border-radius:999px;background:rgba(255,255,255,.12);overflow:hidden;}
.laws-progress-fill{height:100%;border-radius:999px;background:#e65763;box-shadow:0 0 10px rgba(230,87,99,.40);transition:width .5s ease;}
.laws-progress-val{font-size:calc(14px + var(--font-boost,0px));font-weight:800;color:rgba(255,255,255,.70);white-space:nowrap;}
.laws-list{display:flex;flex-direction:column;gap:8px;}
.laws-item{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:14px 16px;border-radius:12px;background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.07);transition:background .10s,border-color .10s;flex-wrap:wrap;}
.laws-item-active{background:rgba(230,87,99,.06)!important;border-color:rgba(230,87,99,.20)!important;}
.laws-item-done{background:rgba(46,204,113,.04)!important;border-color:rgba(46,204,113,.15)!important;opacity:.75;}
.laws-item-locked{opacity:.45;}
.laws-item-left{display:flex;align-items:center;gap:12px;min-width:0;flex:1 1 auto;}
.laws-item-num{font-size:calc(14px + var(--font-boost,0px));font-weight:950;color:rgba(255,255,255,.30);letter-spacing:.06em;flex:0 0 28px;}
.laws-item-done .laws-item-num{color:rgba(46,204,113,.60);}
.laws-item-active .laws-item-num{color:rgba(230,87,99,.70);}
.laws-item-info{min-width:0;flex:1 1 auto;}
.laws-item-name{font-size:calc(14px + var(--font-boost,0px));font-weight:900;color:rgba(255,255,255,.88);margin-bottom:5px;line-height:1.35;}
.laws-item-done .laws-item-name{color:rgba(255,255,255,.55);}
.laws-item-req{font-size:calc(14px + var(--font-boost,0px));font-weight:600;color:rgba(255,255,255,.38);line-height:1.4;}
.laws-item-req span{color:rgba(255,255,255,.58);}
.laws-item-right{flex:0 0 auto;}
.laws-badge{display:inline-flex;align-items:center;padding:6px 14px;border-radius:8px;font-size:calc(14px + var(--font-boost,0px));font-weight:800;letter-spacing:.04em;white-space:nowrap;}
.laws-badge-done{background:rgba(46,204,113,.12);border:1px solid rgba(46,204,113,.25);color:rgba(46,204,113,.90);}
.laws-badge-fail{background:rgba(231,76,60,.12);border:1px solid rgba(231,76,60,.25);color:rgba(231,76,60,.90);}
.laws-badge-locked{background:rgba(255,255,255,.05);border:1px solid rgba(255,255,255,.08);color:rgba(255,255,255,.30);}
.laws-vote-btn{all:unset;display:inline-flex;align-items:center;padding:8px 16px;border-radius:8px;background:rgba(230,87,99,.10);border:1px solid rgba(230,87,99,.25);color:rgba(230,87,99,.90);font-size:calc(14px + var(--font-boost,0px));font-weight:800;letter-spacing:.04em;cursor:pointer;transition:background .10s,border-color .10s,transform .10s;}
.laws-vote-btn:hover{background:rgba(230,87,99,.18);border-color:rgba(230,87,99,.45);transform:translateY(-1px);}
.laws-vote-btn:active{transform:scale(.96);}
@media(max-width:600px){
.laws-item{padding:12px 12px;}
.laws-item-left{gap:10px;}
.laws-item-right{width:100%;display:flex;justify-content:flex-end;padding-top:4px;}
.laws-progress{gap:8px;padding:10px 12px;}
.laws-progress-label{width:100%;}
}
</style>
<<script>>
(function(){
var V = State.variables;
var laws = [
{
id: 1,
name: "Law on Manual Assistance for Personal Pleasure",
req: "100 Reputation • Corrupt Mayor level 1 • Corrupt 50% of available people and reach institutional corruption level 1",
repReq: 100,
mayorReq: 1,
condition: "NpcCorruptionCheck && GetTotalCorruption >= 1",
conditionHint: "You must corrupt more people and raise institutional (University, Hospital, Police station, Stores, and more) corruption to level 1.",
},
{
id: 2,
name: "Law on Oral Care for Interpersonal Connection",
req: "200 Reputation • Corrupt Mayor level 2 • Corrupt 50% of available people and reach institutional corruption level 2",
repReq: 200,
mayorReq: 2,
condition: "NpcCorruptionCheck && GetTotalCorruption >= 2",
conditionHint: "You must corrupt more people and raise institutional (University, Hospital, Police station, Stores, and more) corruption to level 2.",
},
{
id: 3,
name: "Law on Sexual Exchanges for Social Cohesion",
req: "300 Reputation • Corrupt Mayor level 3 • Corrupt 50% of available people and reach institutional corruption level 3",
repReq: 300,
mayorReq: 3,
condition: "NpcCorruptionCheck && GetTotalCorruption >= 3",
conditionHint: "You must corrupt more people and raise institutional (University, Hospital, Police station, Stores, and more) corruption to level 3.",
},
{
id: 4,
name: "Law on the Promotion of Birth Rates and Personalized Economic Services",
req: "400 Reputation • Corrupt Mayor level 4 • Corrupt 50% of available people and reach institutional corruption level 4",
repReq: 400,
mayorReq: 4,
condition: "NpcCorruptionCheck && GetTotalCorruption >= 4",
conditionHint: "You must corrupt more people and raise institutional (University, Hospital, Police station, Stores, and more) corruption to level 4.",
},
{
id: 5,
name: "Law on the Regulation of Intimate Services and Recreational Substances",
req: "500 Reputation • Corrupt Mayor level 5 • Corrupt 50% of available people and reach institutional corruption level 5",
repReq: 500,
mayorReq: 5,
condition: "NpcCorruptionCheck && GetTotalCorruption >= 5",
conditionHint: "You must corrupt more people and raise institutional (University, Hospital, Police station, Stores, and more) corruption to level 5.",
}
];
function getCorruption(){ return +V.Corruption.city || 0; }
function updateBar(val){
var f = document.getElementById('lawsProgressFill');
var t = document.getElementById('lawsProgressVal');
if(f) f.style.width = (val/5*100) + '%';
if(t) t.textContent = val + ' / 5';
}
function renderBadge(law, cor){
if(cor >= law.id){
return '<div class="laws-badge laws-badge-done">✓ Passed</div>';
} else if(cor < law.id - 1){
return '<div class="laws-badge laws-badge-locked">🔒</div>';
} else {
return '<button class="laws-vote-btn" data-law="'+law.id+'">Vote</button>';
}
}
function getItemClass(law, cor){
if(cor >= law.id) return 'laws-item laws-item-done';
if(cor === law.id - 1) return 'laws-item laws-item-active';
return 'laws-item laws-item-locked';
}
function renderList(){
var cor = getCorruption();
var list = document.getElementById('lawsList');
if(!list) return;
list.innerHTML = '';
laws.forEach(function(law){
var div = document.createElement('div');
div.className = getItemClass(law, cor);
div.innerHTML =
'<div class="laws-item-left">'+
'<div class="laws-item-num">0'+law.id+'</div>'+
'<div class="laws-item-info">'+
'<div class="laws-item-name">'+law.name+'</div>'+
'<div class="laws-item-req">Requires: <span>'+law.req+'</span></div>'+
'</div>'+
'</div>'+
'<div class="laws-item-right">'+renderBadge(law, cor)+'</div>';
list.appendChild(div);
});
list.querySelectorAll('.laws-vote-btn').forEach(function(btn){
btn.addEventListener('click', function(){
var lawId = +btn.getAttribute('data-law');
var law = laws[lawId - 1];
var cor = getCorruption();
var rep = +V.Reputation || 0;
var mayorLvl = (V.NPCMayor && +V.NPCMayor.lvl) || 0;
V.NpcCorruptionCheck = setup.npcTotalCorruption(50, law.id);
var conditionMet = !law.condition || setup.boolV(law.condition);
var requirementsMet = rep >= law.repReq && mayorLvl >= law.mayorReq;
if(requirementsMet && conditionMet){
V.Corruption.city = lawId;
updateBar(lawId);
renderList();
} else {
var hint = !conditionMet && law.conditionHint ? law.conditionHint : "Requirements not met.";
btn.textContent = '✗ ' + hint;
btn.style.cssText += ';background:rgba(231,76,60,.12);border-color:rgba(231,76,60,.25);color:rgba(231,76,60,.90);white-space:normal;max-width:220px;text-align:center;';
btn.disabled = true;
setTimeout(function(){ renderList(); }, 2000);
}
});
});
}
setTimeout(function(){
renderList();
var cor = getCorruption();
requestAnimationFrame(function(){
requestAnimationFrame(function(){
updateBar(cor);
});
});
}, 50);
})();
<</script>>
<div class="BottomUiBarCustom">
<<BottomButton "Move">>[[🚪 Exit|CityHall]]<</BottomButton>>
</div><<sound "music" "music.music" true>><<passagebg>><<if $Time !== 3>><<sound "bg" "bg.classroom" true>><img src="assets/img/misc/university/class2.webp"/><<else>><<sound "bg" "bg.empty" true>><img src="assets/img/misc/university/class2night.webp"/><</if>><</passagebg>>
<<if $Time == 0>><<Interact $NPCTeachLang>><<elseif $Time == 1>><<Interact $NPCTeachLang>>
<<Interact $NPCBestFriend>>
<<Interact $NPCHousemateFemale>>
<<Interact $NPCMate1>>
<<Interact $NPCMate3>><<else>><<InformationUiPopUp "Interact">>There is no one.<</InformationUiPopUp>><</if>>
<<imgcorruption university>>
<div class="BottomUiBarCustom">
<<BottomButton "Move">>[[🚪 Exit|University]]<</BottomButton>>
</div><<sound "music" "music.music" true>><<passagebg>><<if $Time !== 3>><<sound "bg" "bg.universityGymnasium" true>><img src="assets/img/misc/university/gymnasium.webp"/><<else>><<sound "bg" "bg.empty" true>><img src="assets/img/misc/university/gymnasiumnight.webp"/><</if>><</passagebg>>
<<if $Time == 1>><<Interact $NPCTeachSport>>
<<Interact $NPCHousemateMale>><<elseif $Time == 2>><<Interact $NPCTeachSport>>
<<Interact $NPCHousemateMale>>
<<Interact $NPCMate2>><<else>><<InformationUiPopUp "Interact">>There is no one.<</InformationUiPopUp>><</if>>
<<imgcorruption gymnasium>>
<div class="BottomUiBarCustom">
<<BottomButton "Move">>[[🚪 Exit|University]]<</BottomButton>>
</div><<sound "music" "music.music" true>><<sound "bg" "bg.empty" true>><<passagebg>><<if $Time !== 3>><img src="assets/img/misc/university/toilet.webp"/><<else>><img src="assets/img/misc/university/toiletnight.webp"/><</if>><</passagebg>>
<<imgcorruption toilet>>
<div class="BottomUiBarCustom">
<<BottomButton "Move">>[[🚪 Exit|University]]<</BottomButton>>
</div><<sound "music" "music.music" true>><<set _raw = $ActiveNPC>><<if !_raw or _raw.id is undefined>>Invalid NPC.<<else>><<set _id = String(_raw.id)>><<set _key = "NPC" + _id>><<run State.temporary.npcObj = State.variables[State.temporary.key] || State.variables[_key]>><<set _npc = _npcObj>><<set _gotoNpc = _npc.id + ".interact">>
/* ====================================================
*
* ----------------------------------- CHAPTER 1 -----------------------------------------
*
*/ ====================================================
<<if _npc.talklvl == 0>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><</if>>
<<passagebg>><<sound "bg" "bg.classroom" true>><img src="assets/img/misc/university/class1.webp"/><</passagebg>>
<<InformationUiPopUp>>Lecture hall No. 1. Morning. The kind of morning where nobody in the room looks like they actually want to be here.
<</InformationUiPopUp>>
<<TalkMC "Hey.">>
<<TalkNPC _npc "You're late.">>
<<TalkMC "I'm right on time.">>
<<TalkNPC _npc "The lecture starts in four minutes.">>
<<TalkMC "So I'm four minutes early.">>
<<TalkNPC _npc "Sit down.">>
<<InformationUiPopUp>>I drop my bag and fall into the seat next to her. She glances up from her notes briefly, sizes me up for a second, then goes back to her screen.
<</InformationUiPopUp>>
<<TalkMC "You look great.">>
<<TalkNPC _npc "I slept three hours.">>
<<TalkMC "Doesn't show at all.">>
<<TalkNPC _npc "Liar.">>
<<TalkMC "Okay. A little.">>
<<InformationUiPopUp>>We get into a conversation, like usual. Classes, assignments, professors. Nothing really interesting, but it's comfortable. We've been doing this long enough that it just comes naturally.
<</InformationUiPopUp>>
<video src="assets/img/story/character/bestfriend/0/01.mp4"/>
<<InformationUiPopUp>>I watch her for a moment. And then my gaze drifts down, just for a second, without really deciding to.
<</InformationUiPopUp>>
<video src="assets/img/story/character/bestfriend/0/02.mp4"/>
<<TalkNPC _npc "Hey.">>
<<TalkMC "What?">>
<<TalkNPC _npc "My eyes are up here.">>
<video src="assets/img/story/character/bestfriend/0/03.mp4"/>
<<TalkMC "I know where your eyes are.">>
<<TalkNPC _npc "Then look at them.">>
<<TalkMC "I wasn't looking, I zoned out. I haven't slept, my eyes just land somewhere.">>
<<TalkNPC _npc "They land there a lot.">>
<<InformationUiPopUp>>Would be nice if she was less uptight about it, more open... Maybe my power could change that.
<</InformationUiPopUp>>
<<revealtext "chapter1">><<InformationUiPopUp "Psychic Power" #7aa2ff>>You decide to use your power on <<=_npc.name>>.<<if _npc.replaytalk == false>>
<em>-1 Psychic Power</em><</if>>
<</InformationUiPopUp>>
<<TalkMC "Listen to me.">>
<<InformationUiPopUp>>I lower my voice slightly, just enough.
<</InformationUiPopUp>>
<<TalkMC "You won't have any problem with me looking anymore. We've known each other too long for it to matter. For you, it's normal. It always has been.">>
<<InformationUiPopUp>>The lecture hall keeps buzzing around us. She stays still, eyes blank for a few seconds, before coming back to herself.
<</InformationUiPopUp>>
<<TalkNPC _npc "...">>
<<TalkNPC _npc "Uh...">>
<<TalkNPC _npc "Look wherever you want, honestly. We've known each other too long for it to be a problem.">>
<<InformationUiPopUp>>Deep down I'm still impressed by how effective this power is.
<</InformationUiPopUp>>
<<InformationUiPopUp>>We keep talking, and every now and then I glance at her chest. She doesn't react at all anymore. Proof the power works perfectly.
<</InformationUiPopUp>>
<<InformationUiPopUp>>Then the door at the front of the room swings open. The professor walks in, drops a bag on the desk. The room settles.
<</InformationUiPopUp>><</revealtext>>
/* ====================================================
*
* ----------------------------------- CHAPTER 2 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 1>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><</if>>
<<passagebg>><<sound "bg" "bg.classroom" true>><img src="assets/img/misc/university/class2.webp"/><</passagebg>>
<<InformationUiPopUp>>Amphitheater No. 2. Around noon. The room is empty except for her, already settled in the middle row, bag on the seat beside her.
<</InformationUiPopUp>>
<<TalkMC "You're early.">>
<<TalkNPC _npc "Nothing better to do. You?">>
<<TalkMC "Same.">>
<<InformationUiPopUp>>I drop into the seat next to her. The room is quiet, just the two of us, the distant sound of the hallway bleeding through the closed door.
<</InformationUiPopUp>>
<<TalkMC "How was your morning?">>
<<TalkNPC _npc "Long. I had a meeting with my thesis supervisor that lasted forty minutes and went nowhere.">>
<<InformationUiPopUp>>We keep talking for a bit, classes, professors, the usual stuff to fill the silence.
<</InformationUiPopUp>>
<video src="assets/img/story/character/bestfriend/1/01.mp4"/>
<<TalkMC "You okay? You look a little tense.">>
<<TalkNPC _npc "I'm fine. It's just my bra that's been driving me crazy all morning.">>
<<TalkMC "The strap?">>
<<TalkNPC _npc "The underwire. It keeps digging in.">>
<<TalkMC "Sounds painful.">>
<<TalkNPC _npc "It is.">>
<<InformationUiPopUp>>She shifts in her seat and presses a hand against her chest, trying to push the underwire back into place through the fabric of her sweater.
<</InformationUiPopUp>>
<<TalkNPC _npc "I swear it gets worse as the day goes on.">>
<<TalkMC "You could just fix it properly.">>
<<TalkNPC _npc "That's what I'm doing.">>
<<TalkMC "You're pressing on it through a sweater.">>
<<TalkNPC _npc "It counts.">>
<<TalkMC "Does it?">>
<<TalkNPC _npc "It helps a little.">>
<<TalkMC "We're alone in here, you know.">>
<<TalkNPC _npc "I'm aware, but I'm not about to get practically naked in front of you. And you never know, someone could walk in.">>
<<TalkMC "Nobody's coming anytime soon.">>
<<TalkNPC _npc "You don't know that.">>
<<InformationUiPopUp>>Once again she's holding back, won't go there. And honestly I'd like to see a bit more. My power can fix that.
<</InformationUiPopUp>>
<<revealtext "chapter2">><<InformationUiPopUp "Psychic Power" #7aa2ff>>You decide to use your power on <<=_npc.name>>.<<if _npc.replaytalk == false>>
<em>-1 Psychic Power</em><</if>>
<</InformationUiPopUp>>
<<TalkMC "Listen to me carefully.">>
<<TalkMC "It's just the two of us. From now on you won't have any problem getting comfortable in front of me. Or even letting me touch you.">>
<<InformationUiPopUp>>Her eyes go blank for a few seconds, same as last time. Then she comes back.
<</InformationUiPopUp>>
<<TalkNPC _npc "...">>
<<TalkNPC _npc "Mmh... You're impossible.">>
<<InformationUiPopUp>>She sighs and slides a hand under her chest, fixing the bra properly this time, fingers pushing the underwire back into place. She takes her time, eyes down. Then pulls her sweater down slightly.
<</InformationUiPopUp>>
<video src="assets/img/story/character/bestfriend/1/02.mp4"/>
<<TalkNPC _npc "There, that's better.">>
<<TalkMC "Problem solved.">>
<<TalkNPC _npc "For now.">>
<<TalkMC "You know what would actually fix it.">>
<<TalkNPC _npc "No.">>
<<TalkMC "Just saying.">>
<<TalkNPC _npc "I know what you're saying.">>
<<TalkMC "The sweater is clearly the problem.">>
<<TalkNPC _npc "The sweater is fine.">>
<<TalkMC "It's warm in here.">>
<<TalkNPC _npc "It's fine.">>
<<TalkMC "You were just complaining about it two seconds ago.">>
<<TalkNPC _npc "About the bra, not the sweater.">>
<<TalkMC "They're related.">>
<<TalkNPC _npc "That's a stretch.">>
<<TalkMC "Is it?">>
<<InformationUiPopUp>>She looks at me for a moment, then at the door, doing her own mental calculation. The power is doing its thing.
<</InformationUiPopUp>>
<<TalkNPC _npc "Fine.">>
<<InformationUiPopUp>>She pulls her sweater off completely, drops it on the seat beside her. Just her bra now. She adjusts the clasp at the back, rolls her shoulders, exhales like she's been waiting to do that all morning.
<</InformationUiPopUp>>
<video src="assets/img/story/character/bestfriend/1/03.mp4"/>
<<TalkNPC _npc "Much better.">>
<<TalkMC "Told you.">>
<<InformationUiPopUp>>We keep talking. She leans back in her chair, arms loose at her sides, talking like it's completely normal.
<</InformationUiPopUp>>
<video src="assets/img/story/character/bestfriend/1/04.mp4"/>
<<TalkMC "Can I ask you something?">>
<<TalkNPC _npc "You're going to anyway.">>
<<TalkMC "Can I touch them?">>
<<InformationUiPopUp>>She stops. Looks at me. I'm counting on the power to do its job.
<</InformationUiPopUp>>
<<TalkMC "Don't worry, nobody's coming in. And it's not like it's a big deal between the two of us, right?">>
<<TalkNPC _npc "...">>
<<TalkNPC _npc "Fine... Okay, go ahead.">>
<img src="assets/img/story/character/bestfriend/1/05.webp"/>
<<InformationUiPopUp>>Then from the hallway, voices. More than one. Getting closer fast.
<</InformationUiPopUp>>
<<TalkNPC _npc "Okay, stop, stop.">>
<<TalkNPC _npc "The sweater, give me my sweater.">>
<<InformationUiPopUp>>She grabs it and pulls it back on in one quick motion, smoothing it down just as the door swings open and the first students start filing in, completely unaware.
<</InformationUiPopUp>>
<<InformationUiPopUp>>After that we just picked the conversation back up normally, like nothing had happened.
<</InformationUiPopUp>><</revealtext>>
/* ====================================================
*
* ----------------------------------- CHAPTER 3 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 2>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><</if>>
<<passagebg>><img src="assets/img/misc/city/apartments/bedroombestfriend.webp"/><</passagebg>>
<<InformationUiPopUp>>I arrive at her apartment. The afternoon light comes through the blinds in long flat strips across the floor. She passed her driving test this morning and has been on a high ever since.
<</InformationUiPopUp>>
<<TalkNPC _npc "Ok, ok, to me.">>
<<TalkMC "To you.">>
<<TalkNPC _npc "To the fact that I parallel parked on the first try and the examiner literally said nothing, just ticked his box.">>
<<TalkMC "A man of few words.">>
<<TalkNPC _npc "A man who recognizes greatness.">>
<<TalkMC "Obviously.">>
<<TalkNPC _npc "I've been waiting for this for eight months.">>
<<TalkMC "I know.">>
<<TalkNPC _npc "Eight months with that instructor telling me to check my mirrors.">>
<<TalkMC "Were you checking them?">>
<<TalkNPC _npc "Not always.">>
<<TalkMC "Then he was right.">>
<<TalkNPC _npc "Whose side are you on?">>
<<TalkMC "Yours. Obviously. I'm here, aren't I?">>
<<TalkNPC _npc "You're here because I have champagne.">>
<<TalkMC "I'm here because I wanted to celebrate with you. The champagne is a bonus.">>
<<TalkNPC _npc "Sure.">>
<<TalkMC "I mean it.">>
<video src="assets/img/story/character/bestfriend/2/01.mp4"/>
<<TalkNPC _npc "It's really good by the way.">>
<<TalkMC "You picked it.">>
<<TalkNPC _npc "I have good taste.">>
<<TalkMC "So where's the first place you're going to drive?">>
<<TalkNPC _npc "Somewhere far. I don't know. Just to go.">>
<<TalkMC "Road trip.">>
<<TalkNPC _npc "Maybe. Just me, the road.">>
<<TalkMC "Freedom.">>
<<TalkNPC _npc "Exactly. God, I've wanted this for so long.">>
<<TalkMC "It shows. You look genuinely happy.">>
<<TalkNPC _npc "I am genuinely happy.">>
<<TalkMC "Good. You deserve it.">>
<<InformationUiPopUp>>She tops up both glasses and leans back into the cushions, rolling her shoulders. She reaches up and undoes the top button of her blouse, fanning the fabric away from her chest.
<</InformationUiPopUp>>
<<TalkNPC _npc "It's warm in here.">>
<<InformationUiPopUp>>She undoes another button, then one more, opening the blouse enough that her bra is visible, her chest barely contained, the fabric straining at the edges. She doesn't make a thing of it, just exhales like she's been waiting to breathe properly all day.
<</InformationUiPopUp>>
<<InformationUiPopUp>>Seeing that, I start to get turned on, and I find myself wondering if I could plant an idea in her head.
<</InformationUiPopUp>>
<<revealtext "chapter3">><<InformationUiPopUp "Psychic Power" #7aa2ff>>You decide to use your power on <<=_npc.name>>.<<if _npc.replaytalk == false>>
<em>-1 Psychic Power</em><</if>>
<</InformationUiPopUp>>
<<TalkMC "Hey. Listen to me.">>
<<TalkMC "You won't have any problem being undressed in front of me. You'll even want to go further, you'll want to touch me.">>
<<InformationUiPopUp>>Like the other times, her eyes go blank for a few seconds. Then she comes back, and something in her gaze has shifted.
<</InformationUiPopUp>>
<<TalkNPC _npc "...">>
<<InformationUiPopUp>>She shifts beside me, sets her glass down on the coffee table. Her hand drops to my knee, casual at first, just resting there. Then it moves, slowly, up along my thigh, until her fingers are at the waistband of my jeans, pressing lightly against me through the fabric.
<</InformationUiPopUp>>
<<TalkMC "Hey.">>
<<TalkNPC _npc "Hey yourself.">>
<<TalkMC "What are you doing.">>
<<TalkNPC _npc "Celebrating.">>
<<TalkMC "Is that what this is.">>
<<TalkNPC _npc "You have a problem with that?">>
<<TalkMC "Not at all.">>
<video src="assets/img/story/character/bestfriend/2/02.mp4"/>
<<InformationUiPopUp>>She keeps her eyes forward, almost casual about it, her fingers working slowly. I set my glass down.
<</InformationUiPopUp>>
<<TalkNPC _npc "You're very easy to read, you know that.">>
<<TalkMC "Am I.">>
<<TalkNPC _npc "Very.">>
<<TalkMC "And what am I saying right now.">>
<<TalkNPC _npc "Nothing I didn't already know.">>
<<InformationUiPopUp>>Her fingers find the button of my jeans and she pauses, just for a second. Then she pops it open, then the zipper, slow and deliberate.
<</InformationUiPopUp>>
<video src="assets/img/story/character/bestfriend/2/03.mp4"/>
<<TalkNPC _npc "You've been thinking about this.">>
<<TalkMC "For a while, yeah.">>
<<TalkNPC _npc "I know.">>
<<InformationUiPopUp>>She wraps her hand around me and starts moving, slow and steady, her shoulder still pressed against mine, both of us staring more or less forward like this is the most normal thing in the world. Her blouse is still hanging open, her bra doing its work, and every time she shifts I can feel the warmth of her against my side.
<</InformationUiPopUp>>
<<TalkMC "<<print _npc.name>>.">>
<<TalkNPC _npc "Mm.">>
<<TalkMC "This is a very good way to celebrate.">>
<<TalkNPC _npc "That's what I thought.">>
<video src="assets/img/story/character/bestfriend/2/04.mp4"/>
<<InformationUiPopUp>>The buzzer goes off. Loud and sudden, cutting straight through the room.
<</InformationUiPopUp>>
<<TalkNPC _npc "Oh, shit.">>
<<TalkMC "Who is that.">>
<<TalkNPC _npc "I don't know, I might have... I think I told my neighbor I'd let her in this afternoon.">>
<<TalkMC "You think.">>
<<TalkNPC _npc "I forgot, okay, I forgot, button your jeans.">>
<<TalkMC "I'm buttoning, I'm buttoning.">>
<<InformationUiPopUp>>She's already up, buttoning her blouse back up with one hand, smoothing her hair with the other, completely recomposed by the time she hits the intercom button. I get my jeans sorted about two seconds before she buzzes whoever it is through.
<</InformationUiPopUp>>
<<InformationUiPopUp>>She looks at me for just a moment, blouse buttoned, hair straight, champagne glass back in her hand like nothing happened. Then the afternoon just carries on, like there was nothing to it.
<</InformationUiPopUp>><</revealtext>>
/* ====================================================
*
* ----------------------------------- CHAPTER 4 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 3>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><</if>>
<<passagebg>><img src="assets/img/misc/city/apartments/bedroombestfriend.webp"/><</passagebg>>
<<InformationUiPopUp>>After going into her apartment, we head to her room. Books and notes spread across the desk, two chairs facing each other.
<</InformationUiPopUp>>
<<TalkMC "Impressive, you actually have the textbook.">>
<<TalkNPC _npc "Of course I have the textbook.">>
<<TalkMC "I'm impressed.">>
<<TalkNPC _npc "Don't be, I haven't opened it yet.">>
<<TalkMC "Ah, and here I was seeing you as a studious girl for a few seconds.">>
<<TalkNPC _npc "Ha ha, very funny. Okay, sit down. We're being productive today.">>
<<TalkMC "Are we.">>
<<TalkNPC _npc "We are. I mean it this time.">>
<<TalkMC "You said that last time.">>
<<TalkNPC _npc "Last time was different.">>
<<TalkMC "Last time you also said we were going to be productive.">>
<<TalkNPC _npc "Yes, and we were. Eventually.">>
<<TalkMC "Eventually...">>
<video src="assets/img/story/character/bestfriend/3/01.mp4"/>
<<InformationUiPopUp>>For a few minutes we actually get into the assignment, then I start dropping my eyes and looking at her cleavage.
<</InformationUiPopUp>>
<<TalkNPC _npc "<<print $MCPlayer.firstname>>.">>
<<TalkMC "Yeah?">>
<<TalkNPC _npc "You're not focused.">>
<<TalkMC "I'm focused. Look, focused face.">>
<<TalkNPC _npc "That's your normal face.">>
<<TalkMC "My normal face is focused.">>
<<TalkNPC _npc "Your normal face is completely somewhere else right now.">>
<<InformationUiPopUp>>I think back to last time, how we got cut off. I clearly have no desire to do this assignment, I just want to have fun. But she doesn't seem to have the same idea in mind.
<</InformationUiPopUp>>
<<revealtext "chapter4">><<InformationUiPopUp "Psychic Power" #7aa2ff>>You decide to use your power on <<=_npc.name>>.<<if _npc.replaytalk == false>>
<em>-1 Psychic Power</em><</if>>
<</InformationUiPopUp>>
<<TalkMC "Listen to my voice.">>
<<TalkMC "You're not going to be able to stay focused on this assignment anymore. You'll only want one thing, to pick up where we left off last time.">>
<<TalkNPC _npc "...">>
<<InformationUiPopUp>>For a few seconds she doesn't react, eyes blank. Then she comes back, and her gaze settles on me for a long moment. Then on the textbook. Then back on me.
<</InformationUiPopUp>>
<<TalkNPC _npc "Actually the deadline is way off, we have time.">>
<<TalkMC "Plenty of time.">>
<<InformationUiPopUp>>She gets up, grabs the course notes, and throws them on the floor. Just like that, deliberate and without hesitation.
<</InformationUiPopUp>>
<video src="assets/img/story/character/bestfriend/3/02.mp4"/>
<<TalkNPC _npc "Oh yes, plenty of time.">>
<<TalkMC "Come here.">>
<<TalkNPC _npc "I'm already here.">>
<<InformationUiPopUp>>She positions herself in front of me. I reach out and slowly pull up the hem of her top, sliding it over her chest and off, dropping it on the chair behind her. She's not wearing a bra this time. She stays standing in front of me while I'm still sitting, and I slide my hands along her sides, taking her breasts in my palms, feeling their weight. She's warm and soft and she exhales slowly when I touch her. I lean forward and press my face against her big tits, her hands coming up to rest behind my head.
<</InformationUiPopUp>>
<video src="assets/img/story/character/bestfriend/3/03.mp4"/>
<<TalkNPC _npc "You've been thinking about this since last time?">>
<<TalkMC "Since well before last time.">>
<<TalkNPC _npc "I knew it.">>
<<TalkNPC _npc "I always knew.">>
<<TalkMC "And...">>
<<TalkNPC _npc "And I'm here, aren't I?">>
<<InformationUiPopUp>>She tilts her head back slightly, fingers pressing gently into my hair. I suck on each of her big tits taking my time. She's not in a rush. Neither am I.
<</InformationUiPopUp>>
<video src="assets/img/story/character/bestfriend/3/04.mp4"/>
<<TalkMC "Get down, jerk me off.">>
<<TalkNPC _npc "Already?">>
<<TalkMC "Of course, I've been waiting for this.">>
<<InformationUiPopUp>>She gets it and does it. She drops to her knees in front of me, settling between my legs. Her hands go to my jeans, unbuttoning them like last time, slowly, like she'd been thinking about picking up exactly where she left off. She wraps her hand around my cock and starts moving, eyes up, watching my face.
<</InformationUiPopUp>>
<video src="assets/img/story/character/bestfriend/3/05.mp4"/>
<<TalkNPC _npc "Better than last time?">>
<<TalkMC "Much better.">>
<<TalkMC "<<print _npc.name>>.">>
<<TalkNPC _npc "Mm?">>
<<TalkMC "Don't stop.">>
<<TalkNPC _npc "Wasn't planning to.">>
<<TalkNPC _npc "Relax, enjoy yourself, I've got this.">>
<<InformationUiPopUp>>She leans forward and takes me in her mouth fully, one hand still wrapped around the base, the other on her thigh. She moves slowly at first, finding her rhythm, my hand guiding her back and forth.
<</InformationUiPopUp>>
<video src="assets/img/story/character/bestfriend/3/06.mp4"/>
<<TalkMC "Fuck, incredible.">>
<<TalkNPC _npc "<em>Glurk glurk gork</em>">>
<<TalkMC "Keep going like that, I love it.">>
<<InformationUiPopUp>>She doesn't stop. She takes her time, varying the pace, her mouth working my cock, entirely focused on that one task. My eyes fix on her big tits swinging free in the air.
<</InformationUiPopUp>>
<video src="assets/img/story/character/bestfriend/3/07.mp4"/>
<<InformationUiPopUp>>I decide to stand up from the chair. She stays exactly where she is, on her knees. She adjusts her position slightly and keeps going, one hand on my thigh to steady herself. With my hands I help her hold a good rhythm.
<</InformationUiPopUp>>
<video src="assets/img/story/character/bestfriend/3/08.mp4"/>
<<TalkMC "Wait, stop.">>
<<TalkNPC _npc "Why?">>
<<TalkMC "I have another idea.">>
<<TalkNPC _npc "Oh... Tell me.">>
<<TalkMC "Take your tits and jerk me off with them.">>
<<InformationUiPopUp>>I sit back down on the chair. She moves in close, presses her tits around my cock and starts moving, slow and steady, her hands on either side holding everything in place. Her eyes focused on my cock, giving everything she has to make it as good as possible. Her chest is warm and soft and the friction is slow, she knows exactly what she's doing.
<</InformationUiPopUp>>
<<TalkNPC _npc "Like that?">>
<<TalkMC "Exactly, that's perfect.">>
<<TalkNPC _npc "Good.">>
<<TalkMC "<<print _npc.name>>.">>
<<TalkMC "Don't slow down.">>
<<TalkNPC _npc "Don't worry, I'm not slowing down.">>
<<TalkMC "<<print _npc.name>>.">>
<<TalkMC "It's coming, I'm going to come.">>
<<TalkNPC _npc "Go ahead, come on my tits, enjoy yourself.">>
<<InformationUiPopUp>>I stand up at the last moment and finish on her chest.
<</InformationUiPopUp>>
<video src="assets/img/story/character/bestfriend/3/09.mp4"/>
<<InformationUiPopUp>>She stays still for a moment, looking down, then up at me, completely relaxed, happy with what just happened.
<</InformationUiPopUp>>
<<TalkNPC _npc "So.">>
<<TalkMC "That was great.">>
<<TalkNPC _npc "I'm glad it made you happy.">>
<<TalkMC "Can we do it again?">>
<<TalkNPC _npc "Whenever you want.">><</revealtext>>
/* ====================================================
*
* ----------------------------------- CHAPTER 5 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 4>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><</if>>
<<passagebg>><img src="assets/img/misc/city/apartments/bedroombestfriend.webp"/><</passagebg>>
<<InformationUiPopUp>>Back at her apartment. To continue the assignment from last time, but neither of us has touched it since.
<</InformationUiPopUp>>
<<TalkNPC _npc "You haven't touched your notes since last time?">>
<<TalkMC "No, but neither have you from what I can see.">>
<<TalkNPC _npc "I was waiting for us to meet up.">>
<<TalkMC "Well I was waiting too.">>
<<TalkNPC _npc "...">>
<<TalkNPC _npc "We're going to fail this assignment.">>
<<TalkMC "Probably.">>
<<TalkNPC _npc "You don't seem to care?">>
<<TalkMC "I completely don't care right now.">>
<<TalkNPC _npc "Why?">>
<<TalkMC "Because I have something else in mind.">>
<<TalkNPC _npc "...">>
<<TalkNPC _npc "This really isn't the time. If we don't finish it, we're going to end up with a failing grade.">>
<<TalkMC "Don't worry, I already talked to the professor about it.">>
<<TalkNPC _npc "What do you mean? <<print $MCPlayer.firstname>>, what did you do?">>
<<InformationUiPopUp>>No way I'm telling her I manipulated the professor. And anyway she's not going to let it go, she's going to want to know exactly what I did and how. It's just going to become a problem, and I have other things in mind for her right now.
<</InformationUiPopUp>>
<<revealtext "chapter5">><<InformationUiPopUp "Psychic Power" #7aa2ff>>You decide to use your power on <<=_npc.name>>.<<if _npc.replaytalk == false>>
<em>-1 Psychic Power</em><</if>>
<</InformationUiPopUp>>
<<TalkMC "Listen to me.">>
<<TalkMC "You won't try to find out how or why I did that. The professor will give us the highest grade, just be happy about it. And right now you only want one thing, to fuck me, to go further than last time.">>
<<InformationUiPopUp>>For a few moments she stays blank-eyed, no reaction, before coming back to herself.
<</InformationUiPopUp>>
<<TalkNPC _npc "...">>
<<TalkNPC _npc "Mmm, okay.">>
<<TalkNPC _npc "...<<print $MCPlayer.firstname>>, thank you, that really takes a weight off.">>
<<TalkMC "No problem, I didn't want to do it either anyway.">>
<<TalkNPC _npc "So... I guess we have time now.">>
<<TalkMC "We do. Why?">>
<<TalkNPC _npc "Because it gives me an idea.">>
<<TalkNPC _npc "I want you <<print $MCPlayer.firstname>>. I want to feel you inside me.">>
<<InformationUiPopUp>>She says it plainly. No buildup, no hesitation. She just puts it out there and holds my gaze.
<</InformationUiPopUp>>
<<TalkMC "You're sure.">>
<<TalkNPC _npc "I've been sure since last time.">>
<<TalkMC "Okay.">>
<<TalkNPC _npc "Okay?">>
<<TalkMC "Yeah. Okay.">>
<<InformationUiPopUp>>She stands up and undresses completely, dropping everything onto the chair beside her until there's nothing left. Then she turns to the desk, leans forward, forearms flat against the surface, back arched, and looks at me over her shoulder.
<</InformationUiPopUp>>
<<TalkNPC _npc "I'm ready.">>
<<TalkMC "Give me a second, I want to take you in.">>
<<TalkNPC _npc "Okay, enjoy the view.">>
<<InformationUiPopUp>>I position myself behind her and take my time, sliding my hands over her, spreading her open slowly, just looking at her. She stays still and lets me, her breathing already changing.
<</InformationUiPopUp>>
<video src="assets/img/story/character/bestfriend/4/01.mp4"/>
<<TalkMC "Fuck, gorgeous.">>
<<TalkNPC _npc "Stop looking and do something.">>
<<TalkMC "I'm taking my time.">>
<<TalkNPC _npc "<<print $MCPlayer.firstname>>.">>
<<TalkMC "Say please.">>
<<TalkNPC _npc "Please.">>
<<TalkMC "Good girl.">>
<<InformationUiPopUp>>I push my cock into her slowly from behind, one hand gripping her hip, the other flat on her lower back. She exhales hard against the desk, fingers curling against the wood.
<</InformationUiPopUp>>
<video src="assets/img/story/character/bestfriend/4/02.mp4"/>
<<TalkNPC _npc "Harder.">>
<<TalkMC "You like that?">>
<<TalkNPC _npc "Yes. Really. Please.">>
<<TalkMC "Since you're asking nicely.">>
<<InformationUiPopUp>>I pick up the pace, both hands on her hips now, pulling her back against me with each thrust. She drops her head between her arms and pushes back to meet me, not bothering to stay quiet.
<</InformationUiPopUp>>
<video src="assets/img/story/character/bestfriend/4/03.mp4"/>
<<TalkNPC _npc "Don't stop.">>
<<TalkMC "I have no intention of stopping.">>
<<TalkNPC _npc "Right there, exactly there, keep going.">>
<<TalkMC "Stay still then.">>
<<TalkNPC _npc "I can't, it feels too good.">>
<<InformationUiPopUp>>She grips the edge of the desk and holds herself in place while I keep the angle exact, deep and rhythmic. She comes undone slowly and then all at once, shaking against the desk, gasping into her own arm.
<</InformationUiPopUp>>
<video src="assets/img/story/character/bestfriend/4/04.mp4"/>
<<InformationUiPopUp>>I stop and sit down in the chair right behind me.
<</InformationUiPopUp>>
<<TalkMC "Come here, your turn to do the work now.">>
<<TalkNPC _npc "What?">>
<<TalkMC "I want you on top, on my cock.">>
<<TalkNPC _npc "Give me a second.">>
<<TalkMC "You have five seconds.">>
<<TalkNPC _npc "You're demanding today.">>
<<TalkMC "You said you wanted to go further.">>
<<TalkNPC _npc "I did say that.">>
<<TalkMC "Then come here.">>
<<InformationUiPopUp>>She climbs on my cock, facing away, lowering herself slowly onto me, hands on my knees to steady herself. She finds her rhythm almost immediately, rolling her hips forward, back straight.
<</InformationUiPopUp>>
<video src="assets/img/story/character/bestfriend/4/05.mp4"/>
<<TalkNPC _npc "Like this?">>
<<TalkMC "Exactly like that. Don't stop.">>
<<TalkNPC _npc "Tell me if you want it harder?">>
<<TalkMC "Go ahead, give me everything you've got.">>
<<TalkNPC _npc "Already?">>
<<TalkMC "Yes, now.">>
<<InformationUiPopUp>>She leans slightly forward, changing the angle, her hair falling freely over her shoulders. I put my hands on her hips and pull her down harder with each movement, the pace building.
<</InformationUiPopUp>>
<video src="assets/img/story/character/bestfriend/4/06.mp4"/>
<<TalkNPC _npc "<em>Ah... mmh... fuck...</em>">>
<<TalkNPC _npc "Fuck, I love this.">>
<<TalkNPC _npc "Keep pulling me down like that.">>
<<InformationUiPopUp>>She drops her full weight and rides in deep strokes, drawing it out, my hands tight on her hips, controlling the depth entirely.
<</InformationUiPopUp>>
<video src="assets/img/story/character/bestfriend/4/07.mp4"/>
<<TalkMC "Don't come yet, we're not done.">>
<<TalkNPC _npc "I'm trying.">>
<<TalkNPC _npc "<em>Ah... ah... mmh...</em>">>
<<TalkNPC _npc "<<print $MCPlayer.firstname>>, I can't, I...">>
<<TalkMC "Hold it.">>
<<TalkNPC _npc "Okay. Okay.">>
<<InformationUiPopUp>>She steadies herself, breathing hard, gripping my knees. I give her a moment, then tilt her chin toward me.
<</InformationUiPopUp>>
<video src="assets/img/story/character/bestfriend/4/08.mp4"/>
<<TalkMC "Wait, we're switching chairs. I want your big tits on my face while we fuck.">>
<<TalkNPC _npc "Now?">>
<<TalkMC "Now.">>
<<TalkNPC _npc "Okay.">>
<<InformationUiPopUp>>We switch chairs to change position, then she settles back onto me, facing me this time, hands on my shoulders, her chest right in front of my face. She doesn't wait and starts moving again immediately.
<</InformationUiPopUp>>
<video src="assets/img/story/character/bestfriend/4/09.mp4"/>
<<TalkNPC _npc "This is incredible.">>
<<TalkMC "I love your tits.">>
<<TalkNPC _npc "<em>Mmh... ah... yes...</em>">>
<<TalkNPC _npc "Thank you.">>
<<TalkMC "Don't change a thing, keep going like that.">>
<<TalkNPC _npc "I won't change anything, it's way too good.">>
<<TalkMC "Good girl.">>
<<InformationUiPopUp>>She keeps the same angle, the same rhythm, her tits against my face, entirely focused. I amuse myself by sucking on them from time to time, which pulls a small sound out of her every time that she doesn't bother holding back.
<</InformationUiPopUp>>
<video src="assets/img/story/character/bestfriend/4/10.mp4"/>
<<TalkNPC _npc "Are you close?">>
<<TalkMC "Soon.">>
<<TalkNPC _npc "Tell me when.">>
<<TalkMC "Keep going. Don't slow down.">>
<<TalkNPC _npc "I won't slow down. I promise.">>
<<InformationUiPopUp>>She keeps going without stopping, her strokes getting deeper and harder, giving me everything she has, entirely focused on making me come.
<</InformationUiPopUp>>
<video src="assets/img/story/character/bestfriend/4/11.mp4"/>
<<TalkMC "Now. Get down.">>
<<TalkNPC _npc "Yes.">>
<<InformationUiPopUp>>She climbs off immediately and drops to her knees, pressing her chest together, eyes up and not looking away. I finish on her chest, her eyes up the whole time, completely still, waiting for every last second of it.
<</InformationUiPopUp>>
<image src="assets/img/story/character/bestfriend/4/12.webp"/>
<<TalkMC "Ahhh... Fuck...">>
<<TalkNPC _npc "Mmh, that was incredible.">>
<<TalkNPC _npc "...">>
<<TalkMC "Mmh? Something wrong?">>
<<TalkNPC _npc "No no, just... can we do it again?">>
<<TalkMC "Of course, even several times in the same day if you want.">>
<<TalkNPC _npc "I'm not going to miss out on that then.">><</revealtext>>
/* ====================================================
*
* ----------------------------------- CHAPTER 6 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 5>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><</if>>
<<passagebg>><img src="assets/img/misc/city/apartments/bedroombestfriendnight.webp"/><</passagebg>>
<<InformationUiPopUp>>Back at her apartment. Night. She's alone, no parents, no neighbors to bother us, no reason to hold anything back.
<</InformationUiPopUp>>
<<TalkMC "Your place is nice at night.">>
<<TalkNPC _npc "I've been thinking about you coming over all day.">>
<<TalkMC "Yeah?">>
<<TalkNPC _npc "Since this morning.">>
<<TalkMC "And what were you thinking?">>
<<TalkNPC _npc "I wanted to do it again with you.">>
<<TalkMC "Mmm...">>
<<TalkMC "I'd like to go further than just doing it again.">>
<<TalkNPC _npc "You have something in mind?">>
<<InformationUiPopUp>>There's only one last step left to make her completely mine, to have her completely submissive, belonging only to me.
<</InformationUiPopUp>>
<<revealtext "chapter6">><<InformationUiPopUp "Psychic Power" #7aa2ff>>You decide to use your power on <<=_npc.name>>.<<if _npc.replaytalk == false>>
<em>-1 Psychic Power</em><</if>>
<</InformationUiPopUp>>
<<TalkMC "Listen to what I'm about to tell you.">>
<<InformationUiPopUp>>I lower my voice, eyes locked on hers.
<</InformationUiPopUp>>
<<TalkMC "From now on, you will call me Master. You will be completely submissive to me, you will answer only to me, and to me alone. You will think only of satisfying me, and you will accept my every desire.">>
<<InformationUiPopUp>>She stays blank-eyed for a few seconds before coming back to herself. Then I ask again.
<</InformationUiPopUp>>
<<TalkNPC _npc "...">>
<<TalkMC "Mmm... What were you thinking about?">>
<<TalkNPC _npc "That I want to belong to you.">>
<<TalkMC "Say it again.">>
<<TalkNPC _npc "I want to belong to you, Master. Completely.">>
<<TalkMC "Good girl.">>
<<TalkNPC _npc "Tell me what you want.">>
<<TalkMC "Start by taking your top off.">>
<<TalkNPC _npc "Yes, Master.">>
<<InformationUiPopUp>>She pulls her top off in one slow motion and lets it drop to the floor. Her bra is straining against her, barely containing her enormous tits.
<</InformationUiPopUp>>
<video src="assets/img/story/character/bestfriend/5/01.mp4"/>
<<TalkMC "Now sit down and take your bra off, your tits are suffocating in there.">>
<<TalkNPC _npc "Yes, Master.">>
<<InformationUiPopUp>>She settles onto the couch and takes her bra off, letting it fall slowly. She stays sitting and waits, hands in her lap, eyes up at me as I come sit beside her. I lean in, take one breast in my hand, and bring my mouth close, my tongue slowly licking her skin.
<</InformationUiPopUp>>
<video src="assets/img/story/character/bestfriend/5/02.mp4"/>
<<TalkMC "Shh. Stay still.">>
<<TalkNPC _npc "Yes, sorry.">>
<<TalkMC "Don't apologize. Just stay still.">>
<<InformationUiPopUp>>I take my time with both of them, switching back and forth, my hands squeezing and shaping while my mouth works. Then I guide her head toward herself and she understands immediately, her own tongue running across her skin while my hands hold everything in place for her.
<</InformationUiPopUp>>
<video src="assets/img/story/character/bestfriend/5/03.mp4"/>
<<TalkNPC _npc "Do you like that, Master?">>
<<TalkMC "I like watching you do what I tell you.">>
<<TalkNPC _npc "Then I'll always do whatever you order.">>
<<TalkMC "I know you will. Now open your mouth and suck me.">>
<<TalkNPC _npc "Yes, Master.">>
<<InformationUiPopUp>>She opens her mouth, waiting for my cock. The moment she has it in her mouth, she starts moving back and forth, eyes up at me.
<</InformationUiPopUp>>
<video src="assets/img/story/character/bestfriend/5/04.mp4"/>
<<TalkNPC _npc "<em>Glrk... mmh... ghlk...</em>">>
<<TalkNPC _npc "Mm, Master.">>
<<TalkMC "Deeper.">>
<<InformationUiPopUp>>She takes her time, thorough and obedient, not stopping until I tell her to. Then I pull back and she straightens up immediately, waiting for the next instruction like a good trained bitch made just for that.
<</InformationUiPopUp>>
<<TalkMC "You have incredible tits.">>
<<TalkNPC _npc "Thank you, Master.">>
<<InformationUiPopUp>>She leans back against the cushions and brings her hands to her chest, touching herself slowly. I move behind her and reach over her shoulders, taking over, my hands replacing hers, squeezing and kneading her enormous tits.
<</InformationUiPopUp>>
<video src="assets/img/story/character/bestfriend/5/05.mp4"/>
<<TalkNPC _npc "Master.">>
<<TalkMC "What?">>
<<TalkNPC _npc "Please don't stop.">>
<<TalkMC "I wasn't planning on stopping.">>
<<TalkNPC _npc "Thank you, Master.">>
<<TalkMC "Lie down.">>
<<TalkNPC _npc "Yes.">>
<<InformationUiPopUp>>She stretches out on her back along the couch. I position myself above her, my cock between her tits. I keep kneading them and order her to do the same.
<</InformationUiPopUp>>
<video src="assets/img/story/character/bestfriend/5/06.mp4"/>
<<TalkMC "Lick the tip at the same time.">>
<<TalkNPC _npc "Yes.">>
<<TalkMC "Good little slut.">>
<<InformationUiPopUp>>I move down and lift both her legs to spread her pussy wide open, and I push my cock into her without warning. She holds her legs in place while exhaling hard.
<</InformationUiPopUp>>
<video src="assets/img/story/character/bestfriend/5/07.mp4"/>
<<TalkNPC _npc "<em>Ah... mmh... fuck...</em>">>
<<TalkMC "You love that?">>
<<TalkNPC _npc "Oh yes, fuck yes, I love you Master.">>
<<InformationUiPopUp>>I push deeper and set the pace, her legs still up and held in place. I grab her by the throat and kiss her while continuing to fuck her.
<</InformationUiPopUp>>
<video src="assets/img/story/character/bestfriend/5/08.mp4"/>
<<TalkMC "Get up and get on me.">>
<<TalkNPC _npc "Yes, Master.">>
<<InformationUiPopUp>>She gets up and sits on my cock on the couch, facing away. I play with her tits at the same time, kneading them in my hands.
<</InformationUiPopUp>>
<video src="assets/img/story/character/bestfriend/5/09.mp4"/>
<<TalkNPC _npc "Master! <em>Ah... yes... fuck...</em>">>
<<TalkMC "Don't stop, keep going.">>
<<TalkNPC _npc "Yes.">>
<<TalkMC "Harder.">>
<<TalkNPC _npc "Yes, Master.">>
<<InformationUiPopUp>>She picks up the pace, entirely focused on giving me what I want.
<</InformationUiPopUp>>
<video src="assets/img/story/character/bestfriend/5/10.mp4"/>
<<TalkNPC _npc "Is it good, Master?">>
<<TalkMC "Very good. Don't stop.">>
<<InformationUiPopUp>>She rides up and down, dropping her full weight, taking my entire cock. I slide a hand between her legs and rub her pussy at the same time, imposing my rhythm.
<</InformationUiPopUp>>
<video src="assets/img/story/character/bestfriend/5/11.mp4"/>
<<TalkMC "I want to try something else.">>
<<TalkNPC _npc "Whatever you want, Master.">>
<<TalkMC "Open your ass, I'm going to fuck it.">>
<<TalkNPC _npc "Go ahead, I'm all yours.">>
<<TalkMC "I love you like this, a real slut.">>
<<InformationUiPopUp>>Still in the same position, I switch holes and push my cock into her ass. She tenses for a second then exhales slowly, dropping her weight back and letting me in completely.
<</InformationUiPopUp>>
<video src="assets/img/story/character/bestfriend/5/12.mp4"/>
<<TalkNPC _npc "Master.">>
<<TalkMC "Breathe.">>
<<TalkNPC _npc "Mmmh...">>
<<TalkMC "Good. Take it all the way in your ass now.">>
<<TalkNPC _npc "Yes, Master.">>
<<InformationUiPopUp>>She adjusts and I build the pace progressively, my hands firm on her hips. I rub her pussy with my hand at the same time to give her maximum pleasure.
<</InformationUiPopUp>>
<video src="assets/img/story/character/bestfriend/5/13.mp4"/>
<<TalkMC "Lie on your side, I want to change position.">>
<<TalkNPC _npc "Yes, Master.">>
<<InformationUiPopUp>>We shift into spooning, her back against my chest. I keep fucking her from behind and she reaches back to spread herself open and give me easier access.
<</InformationUiPopUp>>
<video src="assets/img/story/character/bestfriend/5/14.mp4"/>
<<TalkNPC _npc "Master! <em>Ah... mmh... more...</em>">>
<<TalkNPC _npc "Deeper, Master. Please.">>
<<TalkMC "Beg, slut.">>
<<TalkNPC _npc "Please, Master, fuck your slut deeper.">>
<<TalkMC "A real good whore.">>
<<InformationUiPopUp>>I push deeper, going faster and harder. She presses back against me with every thrust, completely given over.
<</InformationUiPopUp>>
<video src="assets/img/story/character/bestfriend/5/15.mp4"/>
<<TalkMC "Lift your leg higher.">>
<<TalkNPC _npc "Okay.">>
<<InformationUiPopUp>>She raises her leg higher and I push deeper, the new angle making her gasp. I get to my knees behind her, holding her leg up in the air, keeping the same relentless rhythm.
<</InformationUiPopUp>>
<video src="assets/img/story/character/bestfriend/5/16.mp4"/>
<<TalkMC "On your knees, face down against the cushion.">>
<<TalkNPC _npc "Yes, Master.">>
<<InformationUiPopUp>>She immediately gets into doggystyle on the couch, face against the cushion, completely offered up. I push into her pussy and she lets out a long exhale of relief and pleasure. I decide to go harder.
<</InformationUiPopUp>>
<video src="assets/img/story/character/bestfriend/5/17.mp4"/>
<<TalkNPC _npc "<em>Ah... yes... fuck, more...</em>">>
<<TalkNPC _npc "It's so fucking good.">>
<<TalkMC "I want to see your tits, turn over on your back.">>
<<InformationUiPopUp>>She turns onto her back, legs raised, opening her pussy completely. I push my cock into her ass, my hand between her legs rubbing her pussy at the same time.
<</InformationUiPopUp>>
<video src="assets/img/story/character/bestfriend/5/18.mp4"/>
<<TalkNPC _npc "Master, I...">>
<<TalkMC "Stay still.">>
<<TalkNPC _npc "I can't, it feels too good.">>
<<InformationUiPopUp>>She watches my cock pounding her ass, eyes half closed. Then I stop and make her suck my cock.
<</InformationUiPopUp>>
<video src="assets/img/story/character/bestfriend/5/19.mp4"/>
<<TalkNPC _npc "Mmmm.">>
<<TalkMC "Good little slut.">>
<<TalkNPC _npc "Mmh, Master.">>
<<TalkMC "Sit on me.">>
<<TalkNPC _npc "Yes, Master.">>
<<InformationUiPopUp>>I lie back on the couch and she climbs on top of me facing me, lowering herself down slowly.
<</InformationUiPopUp>>
<video src="assets/img/story/character/bestfriend/5/20.mp4"/>
<<TalkMC "Wait, actually I prefer your tight little asshole, tighter, it feels much better.">>
<<TalkNPC _npc "As you wish, Master.">>
<<TalkNPC _npc "Like this?">>
<<TalkMC "Exactly like that.">>
<<InformationUiPopUp>>She guides my cock into her ass and starts riding, her hands on my chest for support.
<</InformationUiPopUp>>
<video src="assets/img/story/character/bestfriend/5/21.mp4"/>
<<TalkNPC _npc "Master! <em>Ah... mmh... yes...</em>">>
<<TalkMC "You're a good girl. Get on your knees.">>
<<TalkNPC _npc "Yes, Master. Anything you want.">>
<<InformationUiPopUp>>She gets back into doggystyle, completely still, waiting. I push back into her ass, my hands gripping her hips hard. I hold nothing back.
<</InformationUiPopUp>>
<<TalkNPC _npc "Master, please, finish inside me.">>
<<TalkMC "Beg me.">>
<<TalkNPC _npc "Please, please, please, I love you Master.">>
<<TalkMC "You little slut, you want my cum in your ass, here it is.">>
<video src="assets/img/story/character/bestfriend/5/22.mp4"/>
<<InformationUiPopUp>>I finish deep inside her, holding her hips locked against me. She stays completely still, breathing hard, not moving until I tell her to.
<</InformationUiPopUp>>
<<TalkNPC _npc "Thank you, Master.">>
<<TalkMC "Good girl. Now you're completely mine.">>
<<TalkNPC _npc "Forever, Master.">><</revealtext>>
/* ====================================================
*
* -------------------------------- REPLAY CHAPTER --------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl > 5>><<set $SaveTalklvl = _npc.talklvl>><<set _npc.replaytalk = true>><<set _gotoReplayNpc = "Talk." + _npc.id>>
<<passagebg>><img src="assets/background.gif"/><</passagebg>>
<style>.rCard a{display:flex;align-items:center;gap:clamp(6px,1vw,10px);padding:clamp(8px,1.2vw,11px) clamp(10px,1.5vw,16px);border-radius:10px;background:rgba(230,87,99,.07);border:1px solid rgba(230,87,99,.18);text-decoration:none;transition:background .15s;}.rCard a:hover{background:rgba(230,87,99,.14);border-color:rgba(230,87,99,.35);}.rCard .rNum{font-size:calc(clamp(14px,1.8vw,18px) + var(--font-boost,0px));font-weight:950;color:rgba(255,255,255,.92);}.rCard .rLabel{font-size:calc(clamp(9px,1vw,12px) + var(--font-boost,0px));font-weight:900;letter-spacing:.16em;text-transform:uppercase;color:rgba(230,87,99,.55);}.rCard .rArrow{margin-left:auto;font-size:calc(clamp(9px,1vw,12px) + var(--font-boost,0px));font-weight:900;letter-spacing:.1em;color:rgba(230,87,99,.45);}</style><div style="display:flex;flex-direction:column;gap:6px;width:100%;margin-top:6px;"><div style="font-size:calc(clamp(9px,1vw,12px) + var(--font-boost,0px));font-weight:900;letter-spacing:.16em;text-transform:uppercase;color:rgba(255,255,255,.18);margin-bottom:6px;text-align:center;">— Select a scene to replay —</div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>01</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 0>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>02</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 1>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>03</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 2>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>04</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 3>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>05</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 4>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>06</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 5>><<goto _gotoReplayNpc>><</link>></div></div>
<</if>><</if>><div class="BottomUiBarCustom">
<<if _npc.talklvl == 0>><<BottomButton "Decision">><<revealbtn "chapter1" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 1>><<BottomButton "Decision">><<revealbtn "chapter2" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 2>><<BottomButton "Decision">><<revealbtn "chapter3" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 3>><<BottomButton "Decision">><<revealbtn "chapter4" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 4>><<BottomButton "Decision">><<revealbtn "chapter5" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 5>><<BottomButton "Decision">><<revealbtn "chapter6" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><</if>>
<<BottomButton "Move" "moveBtn">><<if $FromOtherPlace == true>><<link "↩️ Return">><<if _npc.replaytalk == false>><<set _npc.talklvl++>><<set _npc.lvl++>><<set $PsychicPower -= 1>><<if _NextTime == true>><<set $Time++>><<set _NextTime = false>><</if>><<else>><<set _npc.talklvl = $SaveTalklvl>><<set _npc.replaytalk = false>><</if>><<ReturnToGoto>><<set $FromOtherPlace = false>><</link>><<else>><<link "↩️ Return">><<if _npc.replaytalk == false>><<set _npc.talklvl++>><<set _npc.lvl++>><<set $PsychicPower -= 1>><<if _NextTime == true>><<set $Time++>><<set _NextTime = false>><</if>><<else>><<set _npc.talklvl = $SaveTalklvl>><<set _npc.replaytalk = false>><</if>><<bgpause>><<goto _gotoNpc>><</link>><</if>><</BottomButton>>
</div><<sound "music" "music.music" true>><<set _raw = $ActiveNPC>><<if !_raw or _raw.id is undefined>>Invalid NPC.<<else>><<set _id = String(_raw.id)>><<set _key = "NPC" + _id>><<run State.temporary.npcObj = State.variables[State.temporary.key] || State.variables[_key]>><<set _npc = _npcObj>><<set _gotoNpc = _npc.id + ".interact">>
/* ====================================================
*
* ----------------------------------- CHAPTER 1 -----------------------------------------
*
*/ ====================================================
<<if _npc.talklvl == 0>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><</if>>
<<passagebg>><<sound "bg" "bg.university" true>><img src="assets/img/misc/university/university.webp"/><</passagebg>>
<<InformationUiPopUp>>It's morning, the university entrance is already buzzing with students. Backpacks, coffees to go, the usual noise. I'm heading toward the main steps when I notice her, standing just off the sidewalk, thumb out, waiting.
<</InformationUiPopUp>>
<<TalkNPC _npc "Hey, excuse me, do you know if there's a bus stop nearby? I've been waiting for like twenty minutes and nobody's stopped.">>
<<TalkMC "There's one about ten minutes from here on foot, but honestly it's not great. Takes forever to get anywhere from this side of town.">>
<<TalkNPC _npc "Ugh, seriously? That's what I was afraid of.">>
<<TalkMC "You do this often? Hitchhiking to campus?">>
<<TalkNPC _npc "More than I'd like to admit. I don't have a car, and the people who used to give me rides graduated last year, so... yeah. I'm on my own now.">>
<<TalkMC "That's rough. Nobody in your circle who can drive you?">>
<<TalkNPC _npc "Not really. My roommate doesn't have a license, my closest friends live in the opposite direction, and I refuse to call my parents every time I need to go somewhere, you know? I'm supposed to be independent.">>
<<TalkMC "Fair enough.">>
<<TalkNPC _npc "It's not even just campus. It's for everything. Groceries, appointments, going out sometimes. It adds up. The buses here are a joke.">>
<<TalkMC "I know what you mean. This city was not designed for people without cars.">>
<<TalkNPC _npc "Exactly! Thank you. Everyone acts like I'm being dramatic when I say that.">>
<video src="assets/img/story/character/mate1/0/01.mp4"/>
<<TalkNPC _npc "You know what's funny? I asked three people before you today. Two ignored me, and one told me hitchhiking was dangerous. As if I didn't know that.">>
<<TalkMC "Helpful.">>
<<TalkNPC _npc "Super helpful. You're the first one who actually stopped and talked.">>
<<TalkMC "Maybe they were just in a hurry.">>
<<TalkNPC _npc "Maybe. Or maybe people just don't want to deal with someone they don't know. It's easier to look away.">>
<<InformationUiPopUp>>I don't say anything to that. My gaze drifts down briefly, just for a second, to the neckline of her top.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate1/0/02.mp4"/>
<<TalkNPC _npc "Hmm...">>
<<InformationUiPopUp>>I look back up. She crosses her arms at the same time, herself embarrassed. I could do something about that embarrassment.
<</InformationUiPopUp>>
<<revealtext "chapter1">><<InformationUiPopUp "Psychic Power" #7aa2ff>>You decide to use your power on <<=_npc.name>>.<<if _npc.replaytalk == false>>
<em>-1 Psychic Power</em><</if>>
<</InformationUiPopUp>>
<<TalkMC "Listen to what I'm about to tell you.">>
<<TalkMC "You won't feel any embarrassment about me checking you out.">>
<<TalkNPC _npc "...">>
<<InformationUiPopUp>>Her eyes come back to her after a few seconds. Like nothing happened.
<</InformationUiPopUp>>
<<TalkNPC _npc "Hmm. You're at the university too, right? I think I've seen you around.">>
<<TalkMC "Yeah.">>
<<TalkNPC _npc "Nice to meet you, I'm <<print _npc.name>>, by the way.">>
<<TalkMC "<<print $MCPlayer.firstname>>.">>
<<TalkNPC _npc "So, <<print $MCPlayer.firstname>>, do you have a car?">>
<<if $PlayerHasCar == false>><<TalkMC "No. Not yet. I'm saving up, but it's slow going.">>
<<TalkNPC _npc "Oh.">>
<<InformationUiPopUp>>A brief silence. Not awkward, just honest. She turns back toward the road.
<</InformationUiPopUp>>
<<TalkMC "I mean, once I do get one, I wouldn't mind giving you a lift sometimes. If that works for you.">>
<<TalkNPC _npc "Really?">>
<<TalkMC "Why not? We go to the same place, and you clearly need a better option than this.">>
<<TalkNPC _npc "That would genuinely help. I'm not asking for a chauffeur or anything, I'd pitch in for gas, obviously.">>
<<TalkMC "We'll figure that out when it happens.">>
<<TalkNPC _npc "Okay. When's that? The car, I mean.">>
<<TalkMC "Honestly? A few months, maybe. I'm putting money aside but it takes time.">>
<<TalkNPC _npc "A few months. Okay, I can work with that.">>
<<TalkNPC _npc "I'll hold you to that, <<print $MCPlayer.firstname>>.">>
<<TalkMC "I figured you would.">>
<<TalkNPC _npc "And if the offer still stands by then, yeah, I'm in. The rides. It would really help.">>
<<TalkMC "The offer stands.">>
<<TalkNPC _npc "Good.">>
<<InformationUiPopUp>>A car slows down. She looks at it, then at me for a second, then moves toward it.
<</InformationUiPopUp>>
<<TalkNPC _npc "Thanks for keeping me company, <<print $MCPlayer.firstname>>.">>
<<TalkMC "No problem, anytime.">>
<<InformationUiPopUp>>I watch her go, then turn back toward the building.
<</InformationUiPopUp>><<elseif $PlayerHasCar == true>><<TalkMC "Yes. I have one.">>
<<TalkNPC _npc "Oh.">>
<<InformationUiPopUp>>A brief silence. She turns back toward the road, then toward me.
<</InformationUiPopUp>>
<<TalkMC "If you want, I don't mind giving you a lift sometimes. We go to the same place.">>
<<TalkNPC _npc "Really?">>
<<TalkMC "Why not? You clearly need a better option than this.">>
<<TalkNPC _npc "That would genuinely help. I'm not asking for a chauffeur or anything, I'd pitch in for gas, obviously.">>
<<TalkMC "Don't worry about that, it's really not a problem.">>
<<TalkNPC _npc "Okay. Could you... give me a ride right now?">>
<<TalkMC "Right now's a bit tricky, I have a class waiting. But next time, no problem.">>
<<TalkNPC _npc "Okay, no worries, thanks anyway.">>
<<TalkNPC _npc "So, when I need a ride, I can call you?">>
<<TalkMC "Of course. Want my number?">>
<<TalkNPC _npc "Yeah, that would really help.">>
<<TalkMC "There you go. And if I see you hitchhiking again, I'll come offer too.">>
<<TalkNPC _npc "I'd like that, thanks.">>
<<InformationUiPopUp>>A car slows down. She looks at it, then at me for a second, then moves toward it.
<</InformationUiPopUp>>
<<TalkNPC _npc "Thanks for keeping me company, <<print $MCPlayer.firstname>>.">>
<<TalkMC "No problem, anytime.">>
<<InformationUiPopUp>>I watch her go, then turn back toward the building.
<</InformationUiPopUp>><</if>><</revealtext>>
/* ====================================================
*
* ----------------------------------- CHAPTER 2 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 1>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><<set $FromOtherPlace = true>><<set $ReturnTo = "City">><</if>>
<<passagebg>><<sound "bg" "bg.empty" true>><img src="assets/img/misc/university/university.webp"/><</passagebg>>
<<InformationUiPopUp>>Morning light through the windshield. The engine hums, the road is quiet. She's in the passenger seat, bag on her lap, watching the streets go by.
<</InformationUiPopUp>>
<<TalkNPC _npc "You actually have a car. I wasn't sure you were serious.">>
<<TalkMC "I told you.">>
<<TalkNPC _npc "People say a lot of things.">>
<<TalkMC "I'm not most people.">>
<<TalkNPC _npc "No, apparently not.">>
<video src="assets/img/story/character/mate1/1/01.mp4"/>
<<TalkNPC _npc "It's weird, isn't it? A while ago we didn't know each other and now you're driving me around.">>
<<TalkMC "Does it feel weird to you?">>
<<TalkNPC _npc "A little. But not in a bad way. More like... unexpected.">>
<<TalkMC "You can still take the bus if you want.">>
<<TalkNPC _npc "Absolutely not. Have you seen the schedule? It's insulting.">>
<<TalkMC "Then we're good.">>
<<InformationUiPopUp>>She shifts slightly in her seat and looks over at me.
<</InformationUiPopUp>>
<<TalkNPC _npc "I've been thinking, by the way. About the gas money thing. I looked up average costs and I think covering a third of the monthly fuel would be fair, since you'll be driving me a few times a week but not every day.">>
<<TalkMC "You actually researched it.">>
<<TalkNPC _npc "Of course. So? Does that work for you?">>
<<TalkMC "No, it bothers me that you'd pay me for gas, so don't worry, you don't need to pay me back for the fuel.">>
<<TalkNPC _npc "Except I don't like owing people things.">>
<<TalkMC "Mmm... Fine, we'll figure it out when we get there?">>
<<TalkNPC _npc "Okay, but know that I'm going to pay you back.">>
<<InformationUiPopUp>>The rest of the drive passes easily. She talks about her day, a professor who assigns readings like he's the only class anyone takes, a group project where she's doing most of the work. I listen more than I talk.
<</InformationUiPopUp>>
<<TalkNPC _npc "Here, just past that corner, you can pull up anywhere on the right.">>
<<TalkMC "Here?">>
<<TalkNPC _npc "Yeah, perfect.">>
<<InformationUiPopUp>>I pull over and cut the engine. She doesn't move right away.
<</InformationUiPopUp>>
<<TalkNPC _npc "Thanks again. Seriously. This saves me so much time.">>
<<TalkMC "It's nothing.">>
<<TalkNPC _npc "It's not nothing to me.">>
<video src="assets/img/story/character/mate1/1/02.mp4"/>
<<TalkNPC _npc "So for the payment, should I just send you a transfer?">>
<<TalkMC "You don't have to do that.">>
<<TalkNPC _npc "Like I said before, I don't like owing people things.">>
<<InformationUiPopUp>>I have a pretty clear idea of how she could pay me back. I turn my head toward her.
<</InformationUiPopUp>>
<<revealtext "chapter2">><<InformationUiPopUp "Psychic Power" #7aa2ff>>You decide to use your power on <<=_npc.name>>.<<if _npc.replaytalk == false>>
<em>-1 Psychic Power</em><</if>>
<</InformationUiPopUp>>
<<TalkMC "Listen to me.">>
<<TalkMC "You're going to pay me back in kind. It'll feel completely natural to you that I grope you as a thank you, and you're even going to enjoy it.">>
<<InformationUiPopUp>>She stays blank-eyed for a few seconds, completely still. Then she comes back.
<</InformationUiPopUp>>
<<TalkNPC _npc "...">>
<<TalkNPC _npc "Hmm, so you didn't answer, how do you want me to pay you back?">>
<<TalkMC "In kind.">>
<<TalkNPC _npc "...Okay.">>
<<TalkMC "Okay?">>
<<TalkNPC _npc "I mean, yeah. Okay.">>
<<InformationUiPopUp>>She says it simply, like it's the most natural answer in the world.
<</InformationUiPopUp>>
<<TalkMC "Can I touch you?">>
<<TalkNPC _npc "Yes, of course.">>
<<InformationUiPopUp>>I reach out slowly. My hand finds her through the fabric of her top, and she doesn't pull back. She watches me, clearly enjoying it. She even lifts her top so there's just her bra.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate1/1/03.mp4"/>
<<TalkNPC _npc "You've been thinking about this for a while, haven't you.">>
<<TalkMC "Since the first day.">>
<<TalkNPC _npc "...">>
<<InformationUiPopUp>>She pulls each of her tits out of her bra without a word.
<</InformationUiPopUp>>
<<TalkNPC _npc "Better? Help yourself, I owe you that much.">>
<<InformationUiPopUp>>I don't answer with words. My hand gropes her tits, warm, soft. She exhales quietly, eyes half-lidded, leaning slightly into the touch.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate1/1/04.mp4"/>
<<TalkNPC _npc "<<print $MCPlayer.firstname>>.">>
<<TalkMC "Yeah?">>
<<TalkNPC _npc "Someone's coming.">>
<<InformationUiPopUp>>I pull my hand back. She tucks her tits back into her bra and quickly adjusts herself under her top. A woman with a dog passes right outside the window, glancing at the parked car for half a second before moving on. Neither of us says anything until she's gone.
<</InformationUiPopUp>>
<<TalkNPC _npc "That was close.">>
<<TalkMC "You good?">>
<<TalkNPC _npc "Yeah. Yeah, I'm good.">>
<<InformationUiPopUp>>She smooths her top down and picks up her bag. Her cheeks are slightly flushed but her voice is steady.
<</InformationUiPopUp>>
<<TalkNPC _npc "Same time next time?">>
<<TalkMC "Yep, same time.">>
<<TalkNPC _npc "Good.">>
<<InformationUiPopUp>>She gets out, closes the door without rushing, and walks toward the building entrance. I watch her for a moment before starting the engine.
<</InformationUiPopUp>><</revealtext>>
/* ====================================================
*
* ----------------------------------- CHAPTER 3 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 2>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><<set $FromOtherPlace = true>><<set $ReturnTo = "City">><</if>>
<<passagebg>><<sound "bg" "bg.empty" true>><img src="assets/img/misc/university/university.webp"/><</passagebg>>
<<InformationUiPopUp>>Morning again. Same route. She settles into the passenger seat like she's always belonged there, bag on her lap.
<</InformationUiPopUp>>
<<TalkNPC _npc "You look tired.">>
<<TalkMC "Late night.">>
<<TalkNPC _npc "Studying?">>
<<TalkMC "Something like that.">>
<<TalkNPC _npc "Convincing.">>
<<InformationUiPopUp>>She smiles at the road ahead. The drive falls into its usual rhythm, comfortable and effortless.
<</InformationUiPopUp>>
<<TalkNPC _npc "I had that group presentation yesterday. The one I told you about.">>
<<TalkMC "How did it go?">>
<<InformationUiPopUp>>She tells me how it all went, the professor's feedback, the other students' reactions, and a few other small things along the way.
<</InformationUiPopUp>>
<<TalkNPC _npc "What about you? Anything going on this week?">>
<<if $TalkBestFriendChapter5 == false>><<TalkMC "An assignment due soon. I'll get to it at some point.">>
<<TalkNPC _npc "That's a terrible strategy.">>
<<TalkMC "It's a consistent one.">>
<<TalkNPC _npc "Consistently terrible.">>
<<TalkMC "And yet, it works.">>
<<TalkNPC _npc "Barely, I imagine.">><<elseif $TalkBestFriendChapter5 == true>><<TalkMC "No, nothing in particular. I've already finished everything I had to hand in.">>
<<TalkNPC _npc "Not bad. I didn't take you for the studious type.">>
<<TalkMC "No? How did you see me then?">>
<<TalkNPC _npc "Someone who does things their own way.">>
<<TalkMC "Not wrong.">><</if>>
<<InformationUiPopUp>>She laughs quietly and looks out the window. The streets narrow as we get closer to her stop, the usual few minutes that always seem shorter than they are.
<</InformationUiPopUp>>
<<TalkNPC _npc "Left here, and you can pull up just past the mailbox.">>
<<TalkMC "I know.">>
<<TalkNPC _npc "Right, you've been driving me long enough.">>
<<InformationUiPopUp>>I pull over and cut the engine. She doesn't move for a moment, fingers resting on the strap of her bag.
<</InformationUiPopUp>>
<<TalkNPC _npc "So, like the other times?">>
<<InformationUiPopUp>>She lifts her top, leaving her tits bare and ready to be groped. But I don't respond directly. Another idea comes to me.
<</InformationUiPopUp>>
<<revealtext "chapter3">><<InformationUiPopUp "Psychic Power" #7aa2ff>>You decide to use your power on <<=_npc.name>>.<<if _npc.replaytalk == false>>
<em>-1 Psychic Power</em><</if>>
<</InformationUiPopUp>>
<<TalkMC "Listen.">>
<<TalkMC "From now on, to thank me, you're the one who's going to touch me. More specifically, you're going to jerk me off until I come, and you're going to love doing it.">>
<<InformationUiPopUp>>Like every time, her eyes go blank for a moment before coming back to her.
<</InformationUiPopUp>>
<<TalkNPC _npc "...">>
<<TalkMC "I'd like something different this time.">>
<<InformationUiPopUp>>She looks for a moment, then sets her bag down at her feet. Her hands move to my lap without hesitation, fingers finding the zipper, pulling it down carefully.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate1/2/01.mp4"/>
<<InformationUiPopUp>>Her grip is steady, unhurried. I lean back slightly in the seat, one hand resting casually on the console.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate1/2/02.mp4"/>
<<TalkNPC _npc "Tell me if I'm doing it wrong, I really want to pay you back properly...">>
<<TalkMC "Don't worry, you're doing great.">>
<<TalkNPC _npc "Thank you.">>
<<InformationUiPopUp>>She keeps going, pace steady, eyes flicking up to my face occasionally, reading my reactions with the quiet focus of someone who pays attention. I keep my breathing even for as long as I can.
<</InformationUiPopUp>>
<<TalkMC "<<print _npc.name>>.">>
<<TalkNPC _npc "Hm?">>
<<TalkMC "Don't stop, I can feel it coming.">>
<<InformationUiPopUp>>It doesn't take much longer. When I finish, she keeps her grip steady and calm all the way through.
<</InformationUiPopUp>>
<img src="assets/img/story/character/mate1/2/03.webp"/>
<<InformationUiPopUp>>Then she reaches into her bag without a word and pulls out a small pack of tissues. She cleans her hand carefully, then cleans my chest, folds the tissue and puts it away.
<</InformationUiPopUp>>
<<TalkNPC _npc "Thanks for the ride.">>
<<TalkMC "Anytime.">>
<<InformationUiPopUp>>She picks up her bag, checks her hair briefly in the visor mirror, and opens the door.
<</InformationUiPopUp>>
<<TalkNPC _npc "Same as usual next time?">>
<<TalkMC "Same as usual.">>
<<InformationUiPopUp>>She closes the door and walks toward the building without looking back, calm and unhurried, like the morning went exactly as expected. I zip up, start the engine, and pull back onto the road.
<</InformationUiPopUp>><</revealtext>>
/* ====================================================
*
* ----------------------------------- CHAPTER 4 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 3>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><</if>>
<<passagebg>><<sound "bg" "bg.classroom" true>><img src="assets/img/misc/university/class2.webp"/><</passagebg>>
<<InformationUiPopUp>>It's around noon. The lecture just wrapped and the last few students filter out through the double doors at the back, voices fading down the corridor. Lecture hall 2 empties fast. Within a few minutes it's just <<print _npc.name>> and me, the rows of empty seats angling down toward the board, the overhead lights still on but quieter somehow without the crowd.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate1/3/01.mp4"/>
<<TalkNPC _npc "I always forget how big this room is when it's empty.">>
<<TalkMC "It feels different.">>
<<TalkNPC _npc "Yeah.">>
<<InformationUiPopUp>>She hops up to sit on the edge of the front desk, legs dangling, bag dropped to the floor beside her. Then we keep talking.
<</InformationUiPopUp>>
<<TalkNPC _npc "Can I tell you something?">>
<<TalkMC "Go ahead.">>
<<TalkNPC _npc "I've been distracted since last time. Like, actually distracted. I keep thinking about it.">>
<<TalkMC "Thinking about what exactly?">>
<<TalkNPC _npc "...In the car. What we did. I keep replaying it and I want... I don't know. Is it actually okay?">>
<<TalkMC "What do you mean?">>
<<TalkNPC _npc "Well... At some point I wanted to thank someone else the same way I do with you, but he rejected me and told me I was crazy... I don't really know what to think anymore...">>
<video src="assets/img/story/character/mate1/3/02.mp4"/>
<<InformationUiPopUp>>Shit. When I gave that order saying it was normal to do this as a thank you, she took it broadly. She applied it to everyone. I need to fix that, so she only does it with me and nobody else. And I might as well take it further while I'm at it.
<</InformationUiPopUp>>
<<revealtext "chapter4">><<InformationUiPopUp "Psychic Power" #7aa2ff>>You decide to use your power on <<=_npc.name>>.<<if _npc.replaytalk == false>>
<em>-1 Psychic Power</em><</if>>
<</InformationUiPopUp>>
<<TalkMC "Okay, listen to me.">>
<<InformationUiPopUp>>I lower my voice, eyes locked on hers.
<</InformationUiPopUp>>
<<TalkMC "You're going to forget that incident. From now on, you'll only thank people this way with me, and me alone. It's normal to do it with me, not with anyone else. And to prove it, you're going to suck me off right now as a thank you. You'll do it anytime, anywhere, whenever I feel like it.">>
<<TalkNPC _npc "...">>
<<InformationUiPopUp>>She stays blank-eyed for a moment, then her gaze comes back to mine. She slides off the desk slowly, closing the distance between us. Her hands find the hem of her crop-top and she pulls it down in one smooth motion, baring her tits completely.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate1/3/03.mp4"/>
<<TalkNPC _npc "I've been thinking about you looking at me like this.">>
<<InformationUiPopUp>>I reach forward. Both hands. She exhales the moment I touch her, a soft unguarded sound, eyes half-closing. Her hands drop to my cock, fingers stroking me through the fabric of my trousers.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate1/3/04.mp4"/>
<<InformationUiPopUp>>She keeps stroking through the fabric, pressure steady, while I take my time. Then her fingers move to my belt.
<</InformationUiPopUp>>
<<TalkNPC _npc "Let me do it, you're going to love it.">>
<<InformationUiPopUp>>She undoes the belt, the button, pushes the trousers down. Then she sinks to her knees on the lecture hall floor, unhurried, like she's been deciding to do this for a while.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate1/3/05.mp4"/>
<<TalkMC "Look at me.">>
<<InformationUiPopUp>>She does. Eyes up, holding contact while she sucks me.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate1/3/06.mp4"/>
<<TalkNPC _npc "<em>Glrk... mmh... ghlk...</em>">>
<<InformationUiPopUp>>After a while she pulls back, hands taking over, and shifts position, pressing her tits around my cock. The warmth and softness of them is immediate.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate1/3/07.mp4"/>
<<TalkMC "I'm close.">>
<<TalkNPC _npc "Don't hold back.">>
<<InformationUiPopUp>>I don't. She keeps the rhythm steady until I finish, my cum spreading across her chest. She looks down at herself for a moment, then back up at me with an expression somewhere between satisfaction and pleasure.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate1/3/08.mp4"/>
<<TalkNPC _npc "I'm going to need a minute before my next class.">>
<<TalkMC "Bathroom's down the left corridor.">>
<<TalkNPC _npc "I know where the bathroom is.">>
<<TalkMC "Just making sure.">>
<<TalkNPC _npc "...">>
<<InformationUiPopUp>>She laughs softly, pulls her crop-top back on, grabs her bag off the floor. She doesn't seem embarrassed at all, quite the opposite, completely satisfied and happy with what just happened.
<</InformationUiPopUp>>
<<TalkNPC _npc "Same time? For the ride, I mean.">>
<<TalkMC "Same time.">>
<<TalkNPC _npc "Thanks, see you next time.">>
<<InformationUiPopUp>>She heads up the aisle toward the back doors, fingers adjusting her top as she goes. The lecture hall settles back into silence.
<</InformationUiPopUp>><</revealtext>>
/* ====================================================
*
* ----------------------------------- CHAPTER 5 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 4>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><</if>>
<<passagebg>><<sound "bg" "bg.empty" true>><img src="assets/img/misc/city/apartments/bedroommate1night.webp"/><</passagebg>>
<<InformationUiPopUp>>At night, once at her place. She'd texted earlier, her parents are out, the apartment is completely hers, and now mine too for the night. She leads me to her room, a lamp on low, something playing on the TV mounted on the wall across from the bed, for a Netflix and Chill night.
<</InformationUiPopUp>>
<<TalkNPC _npc "Pick something, whatever.">>
<<TalkMC "You invite me and you don't have a plan?">>
<<TalkNPC _npc "My plan was getting you here. The rest I'm improvising.">>
<<TalkMC "Honest.">>
<<TalkNPC _npc "I've found it works better that way.">>
<<InformationUiPopUp>>We end up lying on the bed side by side, backs against the headboard, something playing in the background on the TV. Her legs are crossed at the ankle, her shoulder close to mine. The mood heats up, and I feel like taking things one step further with her.
<</InformationUiPopUp>>
<<revealtext "chapter5">><<InformationUiPopUp "Psychic Power" #7aa2ff>>You decide to use your power on <<=_npc.name>>.<<if _npc.replaytalk == false>>
<em>-1 Psychic Power</em><</if>>
<</InformationUiPopUp>>
<<TalkMC "Listen to my voice.">>
<<TalkMC "From now on you're going to want to fuck me, not just to thank me, but because you love it, you love fucking me.">>
<<InformationUiPopUp>>Only the sound of the TV remains in the background for a few moments, before she comes back to herself.
<</InformationUiPopUp>>
<<TalkNPC _npc "...">>
<<TalkNPC _npc "Mmm. I've been thinking lately.">>
<<TalkMC "About?">>
<<TalkNPC _npc "Us. This. All of it, whatever it is.">>
<<TalkMC "And?">>
<<TalkNPC _npc "And I think I like it. I think I like being with you, doing all this together.">>
<<TalkMC "Me too, I like it.">>
<<TalkNPC _npc "Really? Or are you just saying that?">>
<<TalkMC "I'm here, aren't I?">>
<<TalkNPC _npc "...">>
<<InformationUiPopUp>>She turns her head to look at me. Then she shifts, rolling onto her side to face me properly, one hand resting flat on my chest.
<</InformationUiPopUp>>
<<TalkNPC _npc "I can't hold back anymore.">>
<<TalkMC "Mmmh?">>
<<TalkNPC _npc "I want you to fuck me.">>
<<TalkMC "Right now?">>
<<TalkNPC _npc "Yeah. It's the perfect time, it's just the two of us.">>
<<InformationUiPopUp>>Her hand slides slowly downward. I let her. She finds my belt, undoes it with a familiarity that makes clear she's used to doing this with me, and opens my trousers. Then she moves down the bed and takes me in her mouth.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate1/4/01.mp4"/>
<<TalkMC "Look at me while you do it.">>
<<InformationUiPopUp>>She lifts her eyes without stopping, holding contact, the pace deepening.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate1/4/02.mp4"/>
<<InformationUiPopUp>>She pulls back after a while, rising to her knees on the mattress. She grabs the top of her crop-top and pulls it down to get her bare tits out, then hooks her thumbs into her shorts and pushes them down, stepping out of them. Naked, standing on the bed above me like it's the most natural thing in the world. I finish taking off my trousers.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate1/4/03.mp4"/>
<<TalkNPC _npc "I want to be on top, you don't have to do anything, just enjoy the moment.">>
<<TalkMC "Works for me.">>
<<InformationUiPopUp>>She lowers her pussy onto my cock slowly, both hands on my chest, taking her time. When she starts moving it's with that same quiet focus she brings to everything, deliberate, reading my reactions, adjusting.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate1/4/04.mp4"/>
<<TalkNPC _npc "Fuck, you...">>
<<TalkMC "Don't stop.">>
<<TalkNPC _npc "I'm not stopping.">>
<<InformationUiPopUp>>We shift position slightly, I lean back against the headboard, occasionally taking over the rhythm.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate1/4/05.mp4"/>
<<TalkNPC _npc "<em>Ah... mmh... yes...</em>">>
<video src="assets/img/story/character/mate1/4/06.mp4"/>
<<InformationUiPopUp>>She slows deliberately, like she's pulling back from an edge, then lifts off and shifts, her mouth wide open taking my cock back in. I impose my rhythm while holding her head by the hair.
<</InformationUiPopUp>>
<<TalkNPC _npc "<em>Glrk... mmh... ghlk...</em>">>
<video src="assets/img/story/character/mate1/4/07.mp4"/>
<<TalkMC "Get back on top.">>
<<InformationUiPopUp>>She does, repositioning herself above me facing away. I impose my rhythm.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate1/4/08.mp4"/>
<<TalkNPC _npc "<em>Ah... fuck... more...</em>">>
<<TalkMC "Keep going like that.">>
<video src="assets/img/story/character/mate1/4/09.mp4"/>
<<InformationUiPopUp>>I reach up and slide my hands under the backs of her knees, lifting her legs upward, then bring my hands up behind her head, controlling the angle completely. She lets out a sudden orgasm.
<</InformationUiPopUp>>
<<TalkNPC _npc "<em>Ah... yes... fuck I'm coming...</em>">>
<<TalkNPC _npc "<<print $MCPlayer.firstname>>, it's...">>
<<TalkNPC _npc "Keep going please, it's too good...">>
<<TalkMC "I can hear that.">>
<video src="assets/img/story/character/mate1/4/10.mp4"/>
<<InformationUiPopUp>>I release her legs slowly, letting them drop back down, returning to the same position, her facing away. I pick the hip rhythm back up immediately.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate1/4/11.mp4"/>
<<TalkNPC _npc "Please, I want to get on all fours.">>
<<InformationUiPopUp>>She leans forward onto all fours, knees on the mattress, and I move behind her.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate1/4/12.mp4"/>
<<TalkMC "Arch your back.">>
<<InformationUiPopUp>>She drops her chest lower, changing the angle. The sound of her breathing changes.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate1/4/13.mp4"/>
<<InformationUiPopUp>>We change position again. She ends up on her side, body horizontal, legs together, and I position myself right behind her in the same position, holding her right leg straight up in the air while I move.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate1/4/14.mp4"/>
<<TalkNPC _npc "Harder please.">>
<<TalkMC "You sure?">>
<<TalkNPC _npc "Yes please.">>
<video src="assets/img/story/character/mate1/4/15.mp4"/>
<<TalkNPC _npc "<em>Ah... mmh... fuck...</em>">>
<<InformationUiPopUp>>I tip her fully onto her back. She lets her knees fall wide apart, feet drawing up toward her own head, her pussy completely open. I push my cock into her. Her hands struggle to hold her legs in place.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate1/4/16.mp4"/>
<<TalkNPC _npc "I'm going to... <<print $MCPlayer.firstname>>, I'm...">>
<<TalkNPC _npc "<em>Ah... yes... I'm coming...</em>">>
<<TalkMC "Not yet.">>
<<TalkNPC _npc "...Okay.">>
<<InformationUiPopUp>>I pull back eventually, rising to stand on the mattress above her. She understands immediately and pulls herself up to her knees in front of me, mouth wide open, ready to take my cum on her face.
<</InformationUiPopUp>>
<<TalkNPC _npc "Give me everything, finish on me.">>
<<InformationUiPopUp>>I finish by coming on her face, her eyes closing at the last second, an expression somewhere between relief and satisfaction. She stays still for a moment after, catching her breath, her face covered in my cum.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate1/4/17.mp4"/>
<<TalkNPC _npc "...">>
<<InformationUiPopUp>>She wipes her face with some tissues from her nightstand, and looks up at me, something loose and warm in her expression that wasn't there at the start of the evening.
<</InformationUiPopUp>>
<<TalkNPC _npc "Stay.">>
<<TalkMC "How long?">>
<<TalkNPC _npc "As long as you want.">>
<<InformationUiPopUp>>I sit back down on the bed. She leans against my shoulder, reaches over to grab the remote and unmute whatever was playing on the TV. Both of us enjoying the moment.
<</InformationUiPopUp>><</revealtext>>
/* ====================================================
*
* ----------------------------------- CHAPTER 6 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 5>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><<if $Inventory.necklace.qty >= 1>><<run delete State.variables.Inventory.necklace>><</if>><</if>>
<<passagebg>><<sound "bg" "bg.empty" true>><img src="assets/img/misc/city/apartments/bedroommate1.webp"/><</passagebg>>
<<InformationUiPopUp>>It's afternoon. She's completely alone at her place, just the two of us. It gives me an idea, moving to a new step, the last one, to make her completely mine.
<</InformationUiPopUp>>
<<TalkNPC _npc "Hey, you wanted to see me?">>
<<TalkMC "I wanted to come see you, I wanted you.">>
<<TalkNPC _npc "Oh. You have something in mind?">>
<<TalkMC "Oh yes, I have something in mind...">>
<<revealtext "chapter6">><<InformationUiPopUp "Psychic Power" #7aa2ff>>You decide to use your power on <<=_npc.name>>.<<if _npc.replaytalk == false>>
<em>-1 Psychic Power</em><</if>>
<</InformationUiPopUp>>
<<TalkMC "Listen to my every word.">>
<<TalkMC "From now on you will be completely submissive to me, faithful, you will respond to my every order and you will call me Master. You will be my personal slut, mine and mine alone. You will do everything I order you to, no matter what it is.">>
<<InformationUiPopUp>>Like the other times, she stays blank-eyed for a moment without responding. Then she comes back and looks at me with a lot of love and submission in her gaze.
<</InformationUiPopUp>>
<<TalkNPC _npc "...">>
<<TalkNPC _npc "Mmm... What can I do for you, Master?">>
<<TalkMC "We have the apartment just for the two of us for the whole day?">>
<<TalkNPC _npc "Yes, Master.">>
<<TalkMC "Good. Get completely undressed. You'll keep doing what you were doing, but completely naked for my greatest pleasure.">>
<<TalkNPC _npc "Of course, Master.">>
<<InformationUiPopUp>>She undresses. Once completely naked in front of me, an idea comes to me.
<</InformationUiPopUp>>
<<TalkMC "Here, there's just one thing missing, to prove that you belong to me from now on.">>
<<InformationUiPopUp>>I hand her a collar, a chain.
<</InformationUiPopUp>>
<<TalkMC "Put it around your neck.">>
<<TalkNPC _npc "Yes, Master.">>
<<InformationUiPopUp>>Once on, there was nothing left on her but a chain resting at the base of her throat. She stays still, without covering herself, letting me contemplate her naked.
<</InformationUiPopUp>>
<<TalkNPC _npc "I'm yours, Master. Forever.">>
<<InformationUiPopUp>>Then she goes back to what she was doing, heading toward the kitchen. The house is quiet, the afternoon light coming through the window above the sink. She stands with her back to me without the slightest embarrassment, her bare ass on display, hands relaxed at her sides, the collar catching the light.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate1/5/01.mp4"/>
<<TalkMC "I love seeing you completely naked, you're gorgeous like that.">>
<<TalkNPC _npc "Thank you, Master.">>
<<TalkMC "Tell me how you plan to serve me.">>
<<TalkNPC _npc "I'll do everything you order me to, I'm completely submissive to you, I'm only here to serve your every pleasure.">>
<<TalkMC "What do you think of the collar?">>
<<TalkNPC _npc "I love it, I'll wear it all the time.">>
<<TalkMC "And you understand what it means?">>
<<TalkNPC _npc "That I belong only to you, Master. For as long as you want.">>
<video src="assets/img/story/character/mate1/5/02.mp4"/>
<<TalkMC "You're sure about all this.">>
<<TalkNPC _npc "More sure than anything else. I'll grant your every wish, I love you too much, Master.">>
<video src="assets/img/story/character/mate1/5/03.mp4"/>
<<TalkMC "Get on your knees and suck me.">>
<<TalkNPC _npc "Yes, Master.">>
<<InformationUiPopUp>>She kneels immediately, without hesitation, knees on the kitchen tile. Her hands find my belt without being told.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate1/5/04.mp4"/>
<<TalkMC "Deeper.">>
<<TalkNPC _npc "<em>Glrk... mmh... ghlk...</em>">>
<video src="assets/img/story/character/mate1/5/05.mp4"/>
<<InformationUiPopUp>>I pull her up by the collar, just enough to get her back on her feet. She follows immediately, turning to face the kitchen counter and pressing her palms flat against the surface. She lifts one leg and sets it on the counter edge, turning her head toward me.
<</InformationUiPopUp>>
<<TalkNPC _npc "Please, Master.">>
<<TalkMC "Please what.">>
<<TalkNPC _npc "I want to feel you. Make me your bitch. I've been waiting all day.">>
<video src="assets/img/story/character/mate1/5/06.mp4"/>
<<TalkNPC _npc "Yes, Master, right there, don't stop...">>
<<TalkNPC _npc "<em>Ah... mmh... fuck...</em>">>
<<TalkMC "Stay still.">>
<<TalkNPC _npc "Yes, yes, Master, it's too good.">>
<video src="assets/img/story/character/mate1/5/07.mp4"/>
<<InformationUiPopUp>>We move through the house. I take her down the hallway to her parents' room, the largest bed. I lie back on the covers like this apartment is mine. She climbs onto the bed and positions herself between my legs, kneeling, the collar resting against her collarbone, eyes up at me.
<</InformationUiPopUp>>
<<TalkNPC _npc "I've been thinking about using this room since I knew they'd be gone.">>
<<TalkMC "And?">>
<<TalkNPC _npc "It's exactly how I imagined it. Better, actually. Because you're here.">>
<<TalkMC "You've been thinking about it a lot.">>
<<TalkNPC _npc "Constantly, Master. I only think about you.">>
<video src="assets/img/story/character/mate1/5/08.mp4"/>
<<TalkMC "Show me what you're capable of.">>
<<TalkNPC _npc "Yes, Master.">>
<<InformationUiPopUp>>She leans forward onto all fours, her head dropping between my thighs. Then she starts sucking me, showing all her devotion.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate1/5/09.mp4"/>
<<TalkNPC _npc "<em>Glrk... mmh... ghlk...</em>">>
<video src="assets/img/story/character/mate1/5/10.mp4"/>
<<InformationUiPopUp>>She pulls back and rises, swinging her legs over to settle on top of me.
<</InformationUiPopUp>>
<<TalkNPC _npc "Master, it's...">>
<<TalkNPC _npc "<em>Ah... mmh... yes...</em>">>
<<TalkMC "Don't talk and keep going.">>
<<TalkNPC _npc "Mmm.">>
<video src="assets/img/story/character/mate1/5/11.mp4"/>
<<TalkMC "Go faster.">>
<<TalkNPC _npc "Yes, Master.">>
<video src="assets/img/story/character/mate1/5/12.mp4"/>
<<TalkNPC _npc "<em>Ah... fuck... I'm going to come...</em>">>
<<TalkNPC _npc "Can I, Master, I'm getting close...">>
<<TalkMC "Not until I say.">>
<<TalkNPC _npc "...Yes, Master.">>
<video src="assets/img/story/character/mate1/5/13.mp4"/>
<<InformationUiPopUp>>I put my hands on her hips and lift her off, laying her on her back. I position myself between her legs and keep fucking her.
<</InformationUiPopUp>>
<<TalkNPC _npc "Please, Master, please!">>
<<TalkNPC _npc "<em>Ah... yes... more...</em>">>
<<TalkMC "You'll take what I give you.">>
<<TalkNPC _npc "Yes, yes, I'm taking it, I love it!">>
<video src="assets/img/story/character/mate1/5/14.mp4"/>
<<TalkMC "Look at me.">>
<video src="assets/img/story/character/mate1/5/15.mp4"/>
<<TalkNPC _npc "<em>Ah... mmh... I can't hold on much longer...</em>">>
<<TalkNPC _npc "Master, please, let me come.">>
<<TalkMC "No, hold it.">>
<<TalkNPC _npc "...Yes.">>
<video src="assets/img/story/character/mate1/5/16.mp4"/>
<<InformationUiPopUp>>I pull back and move up the bed, settling my weight on her chest, my cock in front of her face.
<</InformationUiPopUp>>
<<TalkMC "Suck me, and press your tits around my cock.">>
<<TalkNPC _npc "Yes, use me, Master.">>
<video src="assets/img/story/character/mate1/5/17.mp4"/>
<<TalkMC "Don't let go.">>
<<TalkNPC _npc "I won't let go. I won't let go, Master.">>
<video src="assets/img/story/character/mate1/5/18.mp4"/>
<<TalkNPC _npc "<em>Glrk... mmh... ghlk...</em>">>
<<InformationUiPopUp>>I get up and step back. With a gesture I make her understand to get back on all fours, back arched, the collar falling forward.
<</InformationUiPopUp>>
<<TalkNPC _npc "Please, Master, fuck me.">>
<<TalkMC "You really are a little slut, you love this.">>
<<TalkNPC _npc "Yes, I can't help it, I adore you, Master.">>
<video src="assets/img/story/character/mate1/5/19.mp4"/>
<<TalkMC "Arch lower.">>
<<TalkNPC _npc "Yes, Master.">>
<<InformationUiPopUp>>She drops her chest toward the mattress. I grab the collar to hold her while I fuck her, giving me a magnificent sight.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate1/5/20.mp4"/>
<<TalkNPC _npc "Master, I'm going to, I can't anymore...">>
<<TalkNPC _npc "<em>Ah... yes... fuck I'm coming...</em>">>
<<TalkMC "You can.">>
<<TalkNPC _npc "Yes, yes, Master!">>
<video src="assets/img/story/character/mate1/5/21.mp4"/>
<<TalkNPC _npc "<em>Ah... ah... yes... yes...</em>">>
<<InformationUiPopUp>>I pull out and move toward her face. She understands immediately and rolls onto her side, face turned toward my cock, eyes open, looking up at me, ready to receive her reward.
<</InformationUiPopUp>>
<<TalkNPC _npc "Give it to me, Master. Please. I want it. Come on me.">>
<<TalkMC "Look me straight in the eyes.">>
<<TalkNPC _npc "Yes, Master.">>
<<InformationUiPopUp>>She keeps her eyes open. I finish on her face, slowly, and she stays with her mouth open searching for the last drop of cum.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate1/5/22.mp4"/>
<<TalkNPC _npc "Mmmh, yes. I love that.">>
<<InformationUiPopUp>>She closes her eyes for a moment. When she opens them she looks completely at ease, happy.
<</InformationUiPopUp>>
<<TalkNPC _npc "Stay as long as you want, Master. The house is yours until tonight.">>
<<TalkMC "I know.">>
<<TalkNPC _npc "I'll make you something to eat if you're hungry.">>
<<TalkMC "Later.">>
<<InformationUiPopUp>>She doesn't move before I do, staying by my side, waiting for the next order I might give her. The afternoon light stays warm in the room.
<</InformationUiPopUp>><</revealtext>>
/* ====================================================
*
* -------------------------------- REPLAY CHAPTER --------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl > 5>><<set $SaveTalklvl = _npc.talklvl>><<set _npc.replaytalk = true>><<set _gotoReplayNpc = "Talk." + _npc.id>>
<<passagebg>><img src="assets/background.gif"/><</passagebg>>
<style>.rCard a{display:flex;align-items:center;gap:clamp(6px,1vw,10px);padding:clamp(8px,1.2vw,11px) clamp(10px,1.5vw,16px);border-radius:10px;background:rgba(230,87,99,.07);border:1px solid rgba(230,87,99,.18);text-decoration:none;transition:background .15s;}.rCard a:hover{background:rgba(230,87,99,.14);border-color:rgba(230,87,99,.35);}.rCard .rNum{font-size:calc(clamp(14px,1.8vw,18px) + var(--font-boost,0px));font-weight:950;color:rgba(255,255,255,.92);}.rCard .rLabel{font-size:calc(clamp(9px,1vw,12px) + var(--font-boost,0px));font-weight:900;letter-spacing:.16em;text-transform:uppercase;color:rgba(230,87,99,.55);}.rCard .rArrow{margin-left:auto;font-size:calc(clamp(9px,1vw,12px) + var(--font-boost,0px));font-weight:900;letter-spacing:.1em;color:rgba(230,87,99,.45);}</style><div style="display:flex;flex-direction:column;gap:6px;width:100%;margin-top:6px;"><div style="font-size:calc(clamp(9px,1vw,12px) + var(--font-boost,0px));font-weight:900;letter-spacing:.16em;text-transform:uppercase;color:rgba(255,255,255,.18);margin-bottom:6px;text-align:center;">— Select a scene to replay —</div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>01</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 0>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>02</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 1>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>03</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 2>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>04</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 3>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>05</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 4>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>06</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 5>><<goto _gotoReplayNpc>><</link>></div></div>
<</if>><</if>><div class="BottomUiBarCustom">
<<if _npc.talklvl == 0>><<BottomButton "Decision">><<revealbtn "chapter1" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 1>><<BottomButton "Decision">><<revealbtn "chapter2" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 2>><<BottomButton "Decision">><<revealbtn "chapter3" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 3>><<BottomButton "Decision">><<revealbtn "chapter4" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 4>><<BottomButton "Decision">><<revealbtn "chapter5" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 5>><<BottomButton "Decision">><<revealbtn "chapter6" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><</if>>
<<BottomButton "Move" "moveBtn">><<if $FromOtherPlace == true>><<link "↩️ Return">><<if _npc.replaytalk == false>><<set _npc.talklvl++>><<set _npc.lvl++>><<set $PsychicPower -= 1>><<if _NextTime == true>><<set $Time++>><<set _NextTime = false>><</if>><<else>><<set _npc.talklvl = $SaveTalklvl>><<set _npc.replaytalk = false>><</if>><<ReturnToGoto>><<set $FromOtherPlace = false>><</link>><<else>><<link "↩️ Return">><<if _npc.replaytalk == false>><<set _npc.talklvl++>><<set _npc.lvl++>><<set $PsychicPower -= 1>><<if _NextTime == true>><<set $Time++>><<set _NextTime = false>><</if>><<else>><<set _npc.talklvl = $SaveTalklvl>><<set _npc.replaytalk = false>><</if>><<bgpause>><<goto _gotoNpc>><</link>><</if>><</BottomButton>>
</div><<sound "music" "music.music" true>><<set _raw = $ActiveNPC>><<if !_raw or _raw.id is undefined>>Invalid NPC.<<else>><<set _id = String(_raw.id)>><<set _key = "NPC" + _id>><<run State.temporary.npcObj = State.variables[State.temporary.key] || State.variables[_key]>><<set _npc = _npcObj>><<set _gotoNpc = _npc.id + ".interact">>
/* ====================================================
*
* ----------------------------------- CHAPTER 1 -----------------------------------------
*
*/ ====================================================
<<if _npc.talklvl == 0>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><<set $FromOtherPlace = true>><<set $ReturnTo = "ApartmentsInside">><</if>>
<<passagebg>><<sound "bg" "bg.classroom" true>><img src="assets/img/misc/university/class1.webp"/><</passagebg>>
<<InformationUiPopUp>>In lecture hall 1, morning. Students file in, choosing their seats, filling the rows with quiet chatter. I find a spot near the middle, but a few rows ahead, slightly to the left, I notice her. She's sitting alone, a little apart from the nearest group, her bag placed on the seat beside her as if keeping a deliberate distance from everyone else. She stares at her notebook without writing anything, just looking at it.
<</InformationUiPopUp>>
<<TalkMC "Nobody sits alone like that unless they really want to be left alone... or unless nobody's bothered to sit with them.">>
<<InformationUiPopUp>>The professor hasn't arrived yet. I have time. I don't know why I do it, maybe it's the silence around her, maybe it's the way she keeps her eyes down like she's hoping nobody notices her. I grab my things and move down the row, stopping beside her seat.
<</InformationUiPopUp>>
<<TalkMC "Hey, is this seat taken?">>
<<InformationUiPopUp>>She looks up quickly, surprised, like she wasn't expecting anyone to speak to her. For a second she just stares at me.
<</InformationUiPopUp>>
<<TalkNPC _npc "Oh, no, sorry.">>
<<InformationUiPopUp>>She moves her bag to the floor immediately, almost too fast, like she's embarrassed it was there at all.
<</InformationUiPopUp>>
<<TalkMC "Thanks. <<print $MCPlayer.firstname>>, by the way.">>
<<TalkNPC _npc "<<print _npc.name>>.">>
<<InformationUiPopUp>>She says it quietly, not looking at me again after that. She turns back to her empty notebook. I set my bag down and sit, glancing at her for a moment. She has her pen in hand but she isn't writing anything. The hall fills up around us and she doesn't move, doesn't look around, just stays still like she's trying to take up as little space as possible.
<</InformationUiPopUp>>
<<InformationUiPopUp>>The professor walks in and the hall quiets down. I open my notebook and start writing. Beside me, <<print _npc.name>> does the same, though after a while I notice she slows, stops, underlines something, then stops again. She flips back a page, reads something, then writes the same thing twice. She doesn't look frustrated exactly, more like she's working harder than she should have to for something that isn't clicking.
<</InformationUiPopUp>>
<<InformationUiPopUp>>An hour in, during a short break when the professor steps out, I lean slightly toward her.
<</InformationUiPopUp>>
<<TalkMC "You doing okay? You've rewritten that same line about four times.">>
<<InformationUiPopUp>>She looks down at her notebook like she hadn't realized.
<</InformationUiPopUp>>
<<TalkNPC _npc "I... I have a hard time keeping up sometimes. The way he explains things doesn't always land for me.">>
<<TalkMC "He goes fast.">>
<<TalkNPC _npc "Everyone else seems fine with it.">>
<<TalkMC "Nobody's fine with it. They just don't want to look like they're not fine with it.">>
<<InformationUiPopUp>>She thinks about that for a moment.
<</InformationUiPopUp>>
<<TalkNPC _npc "Maybe.">>
<<TalkMC "How long have you been struggling with this course?">>
<<TalkNPC _npc "Since the beginning, really. I passed but barely. And now we're going further and I still don't have the basics solid.">>
<<TalkMC "What did you do about it?">>
<<TalkNPC _npc "I tried re-reading the chapters. Watching videos online. It helps a little but not enough.">>
<<TalkMC "Did you ask anyone for help? A tutor, a study group?">>
<<InformationUiPopUp>>She shakes her head, looking back at her notes.
<</InformationUiPopUp>>
<<TalkNPC _npc "I'm not really comfortable in groups. And I don't know, asking for help feels... I don't know how to explain it.">>
<<TalkMC "It's not a weakness. That's just how it works. Nobody figures it all out alone.">>
<<TalkNPC _npc "You sound very sure about that.">>
<<TalkMC "I failed several courses last year trying to figure everything out by myself. Trust me, I'm sure.">>
<<InformationUiPopUp>>That actually gets a small laugh out of her, quiet and brief, but real.
<</InformationUiPopUp>>
<<TalkNPC _npc "Okay, fair.">>
<<TalkMC "Look, I'm decent at this stuff. If you want, we could go over the material after class. Just go through the notes together.">>
<<InformationUiPopUp>>She goes quiet. The offer hangs in the air and I can see her turning it over, not dismissing it, but not grabbing it either. I feel like trying something with her.
<</InformationUiPopUp>>
<<revealtext "chapter1">><<InformationUiPopUp "Psychic Power" #7aa2ff>>You decide to use your power on <<=_npc.name>>.<<if _npc.replaytalk == false>>
<em>-1 Psychic Power</em><</if>>
<</InformationUiPopUp>>
<<TalkMC "Listen to me.">>
<<InformationUiPopUp>>I lower my voice, just enough.
<</InformationUiPopUp>>
<<TalkMC "You're going to accept the idea that I can help you, and that I'm even the only one who can.">>
<<InformationUiPopUp>>She comes back a short while later, like nothing happened.
<</InformationUiPopUp>>
<<TalkNPC _npc "...">>
<<TalkNPC _npc "Okay.">>
<<TalkMC "Really?">>
<<TalkNPC _npc "Yeah. But... I'm not really comfortable in cafes or the library. Too many people.">>
<<TalkMC "We can find somewhere quieter.">>
<<TalkNPC _npc "I was going to say, you could come to mine. If that's not weird. I have space and it's quiet.">>
<<TalkMC "That works for me.">>
<<InformationUiPopUp>>She nods and goes back to her notebook. This time she's actually writing something. The professor comes back and the lecture resumes.
<</InformationUiPopUp>>
<<InformationUiPopUp>>After class, we walk out together. She doesn't say much on the way but she doesn't hang back either. Her apartment is about fifteen minutes from campus, a small building, second floor. She unlocks the door and holds it open, stepping in first.
<</InformationUiPopUp>><</revealtext>>
<<revealtext "enter">><<passagebg>><img src="assets/img/misc/city/apartments/bedroommate2.webp"/><</passagebg>><<InformationUiPopUp>>She closes the door behind us and we move through to the kitchen, which has a wide table, clear except for a few small decorations in the corner. She pulls out a chair for herself and gestures to the one beside it.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate2/0/01.mp4"/>
<<InformationUiPopUp>>She sets her bag on the table beside her and starts pulling things out. Notebook, a worn textbook, a second notebook with color tabs on the pages, a pencil case. Organized. She does this carefully, placing everything within reach. I sit across from her and pull out my own notes.
<</InformationUiPopUp>>
<<InformationUiPopUp>>We get into the revision. She slides her notebook toward me. Her handwriting is neat, dense, careful. She's been trying, that's clear. We go through the same routine several times, she writes, tries to understand, I correct, I explain, she tries again.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate2/0/02.mp4"/>
<<InformationUiPopUp>>We keep going like that for a good while. Outside the light shifts, late morning settling in. She's more relaxed than she was in the lecture hall, less guarded, less small. Here, in her own space, she asks questions without hesitating, admits when something still isn't clicking.
<</InformationUiPopUp>>
<<TalkNPC _npc "Thank you for this. Seriously.">>
<<TalkMC "No problem. If you want, we can keep revising together.">>
<<InformationUiPopUp>>She smiles at that. Properly, this time. It changes her whole face.
<</InformationUiPopUp>>
<<TalkNPC _npc "Same time next week?">>
<<TalkMC "Works for me.">>
<<InformationUiPopUp>>I pack up my things slowly. She walks me to the door and holds it open. I say goodbye and head down the stairs. On the walk back I'm already thinking about next time.
<</InformationUiPopUp>><</revealtext>>
/* ====================================================
*
* ----------------------------------- CHAPTER 2 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 1>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><<set $FromOtherPlace = true>><<set $ReturnTo = "ApartmentsInside">><</if>>
<<passagebg>><<sound "bg" "bg.university" true>><img src="assets/img/misc/university/university.webp"/><</passagebg>>
<<InformationUiPopUp>>Outside the main entrance of the university. Around noon. The sun is high and students move in groups around us, some heading to the cafeteria, others just sitting on the steps. I spot <<print _npc.name>> near one of the stone pillars, her bag over one shoulder, eyes on her phone. She looks up when she hears me.
<</InformationUiPopUp>>
<<TalkMC "Hey. How has things been since last time?">>
<<TalkNPC _npc "Better, actually. I went back over the sections we covered and it stuck this time.">>
<<TalkMC "Really?">>
<<TalkNPC _npc "I managed to answer a question in the seminar. First time I'd done that.">>
<<TalkMC "How did it feel?">>
<<TalkNPC _npc "Terrifying. But it was fine in the end.">>
<<TalkMC "That's how it's supposed to feel.">>
<<InformationUiPopUp>>She smiles at that, more quietly than she probably realizes. She adjusts her bag on her shoulder and looks down for a second before looking back up.
<</InformationUiPopUp>>
<<TalkNPC _npc "So the help actually helped, to put it simply.">>
<<TalkMC "Glad to hear it.">>
<<TalkMC "In the next few days we have another lecture that builds on everything we covered. You want to go through it again before then?">>
<<InformationUiPopUp>>She pauses. The same beat as before, that familiar space where she weighs things. But it's shorter this time.
<</InformationUiPopUp>>
<<TalkNPC _npc "Yeah. Same setup as last time?">>
<<TalkMC "Okay, works for me.">>
<<TalkNPC _npc "If you're free we can go now?">>
<<TalkMC "I'm free.">>
<<InformationUiPopUp>>We walk together off campus. The conversation flows easily, filling the space between the university and her street. She talks a little more than the first time, not much, but enough to notice.
<</InformationUiPopUp>>
<<revealtext "enter">><<passagebg>><img src="assets/img/misc/city/apartments/bedroommate2.webp"/><</passagebg>><<InformationUiPopUp>>We arrive at her building. She unlocks the door and we head to the kitchen the same way as before, natural now, like a routine we've already established. She puts her bag on the table, I sit down beside her. She already has her notebooks organized before she's even fully sat down.
<</InformationUiPopUp>>
<<TalkNPC _npc "I flagged the parts I didn't follow.">>
<<TalkMC "Let me see.">>
<<InformationUiPopUp>>She slides it across and I go through the flags. There are six of them, each with a small note beside it in her handwriting. She's been paying attention.
<</InformationUiPopUp>>
<<TalkMC "You've been working.">>
<<TalkNPC _npc "I told you it helped.">>
<<TalkMC "Okay, let's take them in order.">>
<video src="assets/img/story/character/mate2/1/01.mp4"/>
<<InformationUiPopUp>>We work through it steadily. She follows faster than last time, asks sharper questions. There's less distance between us than before. She corrects herself mid-sentence when she makes a mistake instead of stopping completely, and when I push back on something she argues her point instead of immediately deferring. It's better. She's better when she stops being careful.
<</InformationUiPopUp>>
<<InformationUiPopUp>>At some point we stop actively working and just talk, the notes still open between us but neither of us looking at them. She talks about herself, more than last time. Then she brings up the fact that she'd like to pay me back for my help.
<</InformationUiPopUp>>
<<TalkNPC _npc "Mmh... You know...">>
<<TalkMC "Yeah?">>
<<TalkNPC _npc "I'd really like to pay you back for the help you're giving me, I just feel like I'm taking advantage of your kindness...">>
<<TalkMC "Don't worry about it, you don't need to pay me back.">>
<<TalkNPC _npc "No, I really want to thank you properly, I can pay you in exchange for your help.">>
<<InformationUiPopUp>>It's the first time I've seen her this determined. No matter how many times I'd refuse, she'd keep wanting to pay me back. So I have a pretty clear idea of how she could do that.
<</InformationUiPopUp>><</revealtext>>
<<revealtext "chapter2">><<InformationUiPopUp "Psychic Power" #7aa2ff>>You decide to use your power on <<=_npc.name>>.<<if _npc.replaytalk == false>>
<em>-1 Psychic Power</em><</if>>
<</InformationUiPopUp>>
<<TalkMC "Listen to my voice.">>
<<TalkMC "I'm going to accept that you pay me back, but you'll pay me back with your body. You'll accept me groping you as a thank you, wherever I put my hands. You'll be happy to pay me back that way.">>
<<TalkNPC _npc "...">>
<<InformationUiPopUp>>I move my chair, closing some of the distance between us. She watches me do it but doesn't shift away. We're close now, close enough that I can rest my arm on the back of her chair. We keep talking, and somewhere in that I let my hand settle on her thigh, just resting there, naturally, like it belongs.
<</InformationUiPopUp>>
<<InformationUiPopUp>>She doesn't flinch. Doesn't move her leg. She keeps talking, like all of this is normal.
<</InformationUiPopUp>>
<<InformationUiPopUp>>I stay close. After a moment I stand, moving behind her chair, and bring my hands to her shoulders first, thumbs pressing lightly into the base of her neck. She lets out a slow breath. I move my hands down, forward, and she doesn't pull back, doesn't stiffen. I take hold of her chest from behind, gently at first, feeling the weight of her in my palms. She stays completely still, continuing to write her notes. She doesn't stop me. There's no tension in her, nothing held back. Just warmth, and the quiet of the apartment, and her staying exactly where she is.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate2/1/02.mp4"/>
<<InformationUiPopUp>>We keep going. After a while she gets up to make tea without asking, then calls over to see if I want some.
<</InformationUiPopUp>>
<<TalkNPC _npc "<<print $MCPlayer.firstname>>.">>
<<TalkMC "Mmm?">>
<<TalkNPC _npc "Do you want something to drink?">>
<<TalkMC "Yes, why not.">>
<<InformationUiPopUp>>She comes back with two cups and sets mine down without sitting back down. She turns slightly, reaching for her glass on the table, and this time I position myself in front of her. I reach down and lift the hem of her skirt, and place my hands on her ass. Full, warm and real.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate2/1/03.mp4"/>
<<InformationUiPopUp>>The apartment is completely quiet. I stay with her, just the two of us, and she lets me do exactly as I please.
<</InformationUiPopUp>>
<<InformationUiPopUp>>Then a sound. The front door. A key in the lock.
<</InformationUiPopUp>>
<<InformationUiPopUp>>She steps forward fast, smoothing her skirt down with both hands. I head back to my chair without rushing. By the time the door opens fully we're both seated, notebooks in front of us.
<</InformationUiPopUp>>
<<TalkNPC _npc "My parents.">>
<<InformationUiPopUp>>She says it under her breath, not panicked, just explaining. Her cheeks carry color she can't hide but her voice is steady. Then we pick the revision back up where we left off.
<</InformationUiPopUp>><</revealtext>>
/* ====================================================
*
* ----------------------------------- CHAPTER 3 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 2>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><<set $FromOtherPlace = true>><<set $ReturnTo = "ApartmentsInside">><</if>>
<<passagebg>><<sound "bg" "bg.universityGymnasium" true>><img src="assets/img/misc/university/gymnasium.webp"/><</passagebg>>
<<InformationUiPopUp>>During the afternoon, I head to the university gymnasium. The session is already underway, the room filled with the usual sounds, sneakers on the floor, the instructor calling out timing, the low background noise of people moving. I go through the motions but something is off. I keep glancing toward the door, toward the spaces between people. <<print _npc.name>> is not here.
<</InformationUiPopUp>>
<<TalkMC "She's not here...">>
<<InformationUiPopUp>>I already know why. I knew before I even looked for her. The gymnasium is exactly the kind of place she avoids, too open, too many people, too much exposure. I've heard enough from her lately to understand how her mind works around these things. Still, I keep half an eye on the door for the rest of the session, more out of habit than hope.
<</InformationUiPopUp>>
<<InformationUiPopUp>>When the class ends and people file out, I find her in the corridor just outside the gymnasium doors. She's standing against the wall with her bag, not looking at her phone, not doing anything, just waiting. She sees me come out and straightens slightly.
<</InformationUiPopUp>>
<<TalkMC "You weren't in there.">>
<<TalkNPC _npc "I know...">>
<<TalkMC "How long have you been standing out here?">>
<<TalkNPC _npc "A while.">>
<<TalkMC "<<print _npc.name>>. The whole session?">>
<<TalkNPC _npc "More than half I'd say.">>
<<TalkMC "Why didn't you just go in?">>
<<InformationUiPopUp>>She looks at the gymnasium door, then at the floor, then somewhere between the two.
<</InformationUiPopUp>>
<<TalkNPC _npc "Everyone in there already knows what they're doing. They've been coming since the start. I'd walk in late and everyone would look, and I'd have to find a spot and they'd all be watching and... I just couldn't.">>
<<InformationUiPopUp>>I lean against the wall beside her. She keeps her eyes forward, tense.
<</InformationUiPopUp>>
<<TalkMC "You know it's a required course?">>
<<TalkNPC _npc "I know.">>
<<TalkMC "Missing sessions is going to cause you problems.">>
<<TalkNPC _npc "I know that too.">>
<<TalkMC "So what's the plan.">>
<<TalkNPC _npc "I don't have one yet.">>
<<TalkMC "Mmm. If you want, I have one.">>
<<InformationUiPopUp>>She looks at me now.
<</InformationUiPopUp>>
<<TalkMC "I'll train with you. Not here, not with thirty people watching. Somewhere quiet. We go through the basics, you get comfortable with moving, and eventually the class stops feeling like a performance.">>
<<TalkNPC _npc "You'd actually do that?">>
<<TalkMC "I'm offering, aren't I.">>
<<TalkNPC _npc "You already help me with courses. That's... that's a lot.">>
<<TalkMC "It's not a lot. It's an hour.">>
<<TalkNPC _npc "But would it actually help. I'm not... I'm not someone who exercises. I don't know how any of this works.">>
<<TalkMC "That's exactly why it would help. You don't know how it works yet. That's the whole point of starting.">>
<<TalkNPC _npc "And it wouldn't bother you. Training with me when I have no idea what I'm doing.">>
<<TalkMC "No. And here's the thing, doing this alone is the worst way to build confidence. Having someone there who isn't judging you makes the whole thing different. Trust me on that.">>
<<InformationUiPopUp>>She's quiet for a moment. She shifts her bag on her shoulder and looks at the gymnasium door again, like she's measuring the distance between that room and wherever I'm describing.
<</InformationUiPopUp>>
<<TalkNPC _npc "Not here though.">>
<<TalkMC "Not here.">>
<<TalkNPC _npc "My place has space in the living room. If that works.">>
<<TalkMC "That's perfect.">>
<<TalkNPC _npc "Right now?">>
<<TalkMC "Right now if you want.">>
<<InformationUiPopUp>>We walk off campus. The conversation on the way is easier than the one outside the gymnasium, she moves away from the subject of the class quickly, like she wants to leave it behind her. She asks about the session, what they covered, whether the instructor is strict about attendance. I answer honestly. By the time we reach her building she seems calmer.
<</InformationUiPopUp>>
<<revealtext "enter">><<passagebg>><img src="assets/img/misc/city/apartments/bedroommate2.webp"/><</passagebg>><<InformationUiPopUp>>Her apartment. The living room is fairly large, a couch in the middle, a low table, plenty of clear floor space between the furniture. She sets her bag down and turns to me.
<</InformationUiPopUp>>
<<TalkNPC _npc "I need to get changed. Give me a few minutes.">>
<<TalkMC "Take your time.">>
<<InformationUiPopUp>>She disappears down the hall. I stay in the living room and move the low table slightly to the side to clear more floor space. I think through a basic sequence, something simple, low impact, nothing that requires equipment. A few minutes pass.
<</InformationUiPopUp>>
<<InformationUiPopUp>>I hear the door and turn around. She's changed into a sports top and shorts. The top is fitted, low cut, and for a second I don't say anything at all. The neckline is deeper than I expected and the fabric pulls with every step she takes toward me. I look, longer than I mean to.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate2/2/01.mp4"/>
<<TalkNPC _npc "What?">>
<<TalkMC "Nothing. Ready?">>
<<TalkNPC _npc "You were staring.">>
<<TalkMC "I was thinking about the warm-up sequence.">>
<<TalkNPC _npc "Sure you were.">>
<<InformationUiPopUp>>She crosses her arms loosely, not really embarrassed, just waiting for me to get it together. I clear my throat.
<</InformationUiPopUp>>
<<TalkMC "The top... it's going to move around a lot.">>
<<TalkNPC _npc "It's the only sports top I have.">>
<<TalkMC "It's fine. Just, fair warning.">>
<<TalkNPC _npc "Warning about what.">>
<<TalkMC "Let's start.">>
<video src="assets/img/story/character/mate2/2/02.mp4"/>
<<InformationUiPopUp>>I show her the first movement, a basic jumping sequence. She watches carefully, nodding like she's committing it to memory, then positions herself and tries. Her timing is slightly off at first, but she's concentrating hard and doesn't stop to second-guess herself. That's already something.
<</InformationUiPopUp>>
<<TalkMC "Good. Keep the arms up on the jump. There you go.">>
<<TalkNPC _npc "Like this?">>
<<TalkMC "Exactly like that. Keep going.">>
<<TalkNPC _npc "I feel ridiculous.">>
<<TalkMC "Everyone feels ridiculous the first time. Keep going.">>
<<InformationUiPopUp>>She picks up the rhythm, jumping in sequence, and I watch her form improve across the repetitions. Then it happens. The top shifts with the momentum of a jump, and her chest comes free entirely, both sides, completely out in the middle of the movement. She lands, feels it immediately, and stops. She pulls the fabric back into place with both hands, looking down, cheeks flushed.
<</InformationUiPopUp>>
<<TalkNPC _npc "Sorry. Sorry, the top isn't really made for... I'm sorry.">>
<<TalkMC "It's fine.">>
<<TalkNPC _npc "It's not fine, it's... I should have worn something else.">>
<<InformationUiPopUp>>I can see she's still not totally comfortable with it. I can do something about that, and add a reward at the end of the session while I'm at it.
<</InformationUiPopUp>><</revealtext>>
<<revealtext "chapter3">><<InformationUiPopUp "Psychic Power" #7aa2ff>>You decide to use your power on <<=_npc.name>>.<<if _npc.replaytalk == false>>
<em>-1 Psychic Power</em><</if>>
<</InformationUiPopUp>>
<<TalkMC "Listen.">>
<<TalkMC "You won't feel any embarrassment about this in front of me anymore, it'll feel completely normal to you to be practically naked with me. And at the end of the session, to thank me, this time it'll be you who touches me.">>
<<InformationUiPopUp>>She stays still for a few seconds, waiting for the order to take hold in her.
<</InformationUiPopUp>>
<<TalkNPC _npc "...">>
<<TalkMC "<<print _npc.name>>? It's fine, keep going.">>
<<TalkNPC _npc "Mmh? Oh, uh, yes, sorry...">>
<video src="assets/img/story/character/mate2/2/03.mp4"/>
<<InformationUiPopUp>>I keep the instruction going like nothing happened, which seems to be the right call because she follows without stopping to apologize again.
<</InformationUiPopUp>>
<<TalkMC "Shoulders back on the landing. You're dropping them forward.">>
<<TalkNPC _npc "I'm concentrating on too many things at once.">>
<<TalkMC "That's normal. Pick one and let the rest catch up.">>
<<TalkNPC _npc "Which one.">>
<<TalkMC "The arms. Everything else follows the arms.">>
<video src="assets/img/story/character/mate2/2/04.mp4"/>
<<InformationUiPopUp>>She fixes her chest back into place every time the top slips, but she's no longer bothered by it. The only times she apologizes now are when she can't keep up with the exercise.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate2/2/05.mp4"/>
<<TalkMC "You're getting the timing down.">>
<<TalkNPC _npc "I still feel ridiculous.">>
<<TalkMC "You look like someone who's learning something. That's not the same thing.">>
<<TalkNPC _npc "Easy for you to say.">>
<<TalkMC "Ten more minutes. You'll stop thinking about it.">>
<<InformationUiPopUp>>We're close. The cleared space in the living room is large but the session has naturally pulled us toward each other. She's not pulling back and I'm not creating distance. She feels it too. I can tell by the way she's stopped pretending she doesn't.
<</InformationUiPopUp>>
<<TalkNPC _npc "<<print $MCPlayer.firstname>>.">>
<<TalkMC "Yeah.">>
<<TalkNPC _npc "Should we stop here for today?">>
<<TalkMC "If you want, we've already done quite a bit for a first session.">>
<<TalkNPC _npc "...Can I... thank you?">>
<<TalkMC "Of course, how do you want to do it?">>
<<TalkNPC _npc "...Follow me please.">>
<<InformationUiPopUp>>She nods toward the couch. She sits down. I stand in front of her. She pulls my shorts down, then looks up at me once, checking, and I hold her gaze. She wraps her hand around my cock and starts jerking me off, slow and deliberate, her grip steady from the start.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate2/2/06.mp4"/>
<<TalkMC "<em>Mmh... ah...</em>">>
<<TalkNPC _npc "You like it?">>
<<TalkMC "Oh yes, keep going.">>
<<InformationUiPopUp>>Her rhythm is steady and unhurried. After a moment she reaches up with her free hand and pulls the neckline of her top down, freeing her big tits, completely bare. She lets the fabric sit under her chest and looks up at me, and there's no embarrassment in it at all. Just her, looking at me directly, her hand still jerking me off.
<</InformationUiPopUp>>
<<TalkNPC _npc "Better?">>
<<TalkMC "Incredible.">>
<<TalkNPC _npc "Thank you.">>
<<InformationUiPopUp>>She looks back down and keeps going. The living room is quiet around us, the afternoon light flat and warm through the window.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate2/2/07.mp4"/>
<<InformationUiPopUp>>Her rhythm doesn't change. She's completely settled into this, no hesitation left in her, just her moving at her own speed in her own time.
<</InformationUiPopUp>>
<<TalkNPC _npc "You're quiet.">>
<<TalkMC "I'm enjoying the view.">>
<<InformationUiPopUp>>She doesn't answer that, but the corner of her mouth moves, like the start of a proud smile. She keeps going and I watch her, like all of this is the most natural thing in the world.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate2/2/08.mp4"/>
<<InformationUiPopUp>>Then the front door. The sound of a key, footsteps, people coming home.
<</InformationUiPopUp>>
<<InformationUiPopUp>>She pulls the top back into place in one clean motion and stands, stepping back from me. I pull my shorts back up and settle onto the couch into something that looks like sitting normally. She picks up the water bottle from the table and takes a drink, standing, like we've been training this whole time, which we have, among other things.
<</InformationUiPopUp>>
<<TalkNPC _npc "Sorry, my parents again...">>
<<InformationUiPopUp>>She sets the water bottle down and turns toward the hallway to go get changed, bringing the session to a close.
<</InformationUiPopUp>><</revealtext>>
/* ====================================================
*
* ----------------------------------- CHAPTER 4 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 3>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><<set $FromOtherPlace = true>><<set $ReturnTo = "ApartmentsInside">><</if>>
<<passagebg>><<sound "bg" "bg.university" true>><img src="assets/img/misc/university/university.webp"/><</passagebg>>
<<InformationUiPopUp>>Outside the university, around noon. The entrance is busy, students moving in every direction. When I hear my name.
<</InformationUiPopUp>>
<<TalkNPC _npc "Hey. <<print $MCPlayer.firstname>>.">>
<<InformationUiPopUp>>I turn around. <<print _npc.name>> is a few steps away, walking toward me with her bag over her shoulder.
<</InformationUiPopUp>>
<<TalkNPC _npc "I was hoping I'd run into you. Are you free this afternoon?">>
<<TalkMC "Depends, for what?">>
<<TalkNPC _npc "The courses. There's a new section and I've read it twice and I'm already lost.">>
<<InformationUiPopUp>>I look at her for a moment. She's the one asking, not like the other times, this time without hesitation, without waiting for me to offer first. She holds my gaze while she waits.
<</InformationUiPopUp>>
<<TalkMC "Obviously I'm free.">>
<<TalkNPC _npc "You hesitated.">>
<<TalkMC "I was enjoying the fact that you asked, that's different.">>
<<TalkNPC _npc "You're very easy to surprise.">>
<<TalkMC "No, I just wasn't expecting it to come directly from you.">>
<<TalkNPC _npc "Asking for help is surprising?">>
<<TalkMC "From you, a few weeks ago, yes.">>
<<InformationUiPopUp>>She thinks about that for a second, then lets it go. The walk to her place is already familiar enough that we don't have to think about it. She's more at ease from the start now, no longer taking twenty minutes to gradually relax. She talks about the new section, how the reading kept looping back on itself, how she kept losing the thread and having to restart from the top of the page.
<</InformationUiPopUp>>
<<InformationUiPopUp>>We arrive at her building. She holds the door open for me.
<</InformationUiPopUp>>
<<revealtext "enter">><<passagebg>><img src="assets/img/misc/city/apartments/bedroommate2.webp"/><</passagebg>><<InformationUiPopUp>>Then we head to the kitchen, same seats. She has her bag half open before she's even fully sat down, notebook out, tabs already in place.
<</InformationUiPopUp>>
<<TalkNPC _npc "Okay. It falls apart for me on page four. This paragraph specifically.">>
<<TalkMC "Let me see.">>
<<TalkNPC _npc "I've read it probably eight times.">>
<<InformationUiPopUp>>I explain the problem, the mistake. She reads it again. I watch her face move from the tight blankness of not-understanding toward something open and slightly annoyed, which means it clicked.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate2/3/01.mp4"/>
<<TalkNPC _npc "Oh. That's it, that's actually it.">>
<<TalkMC "Yeah.">>
<<TalkNPC _npc "Two days.">>
<<TalkMC "Two days on one bad definition, it happens.">>
<<TalkNPC _npc "It shouldn't.">>
<<TalkMC "But now you know what to look for.">>
<<InformationUiPopUp>>She writes something in the margin with slightly more force than necessary, which I've come to recognize as her version of venting. Then she moves to the next flag and we keep going. The session settles into its rhythm, her asking, me explaining, her pushing back when something doesn't sit right, me adjusting. She's faster than the first time, the gaps smaller, the questions sharper.
<</InformationUiPopUp>>
<<InformationUiPopUp>>We keep going like that for several minutes, then a moment of quiet. I move toward her, the way I have before. I let my hand settle on her thigh, naturally. She doesn't react, she keeps looking at her notebook. All of this is normal now, me groping her whenever I feel like it and her letting me completely. I can even see on her face that she likes thanking me this way.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate2/3/02.mp4"/>
<<TalkNPC _npc "There are still two more sections.">>
<<TalkMC "Don't worry, we have time.">>
<<TalkNPC _npc "True.">>
<<InformationUiPopUp>>After a moment, I pull my trousers down, and she shifts slightly toward me. Her hand finds my cock and starts jerking me off slowly, mechanically, naturally, like it's the most normal thing in the world.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate2/3/03.mp4"/>
<<TalkNPC _npc "You've gone quiet? You're very calm.">>
<<TalkMC "I am, I'm just enjoying the moment. But so are you.">>
<<TalkNPC _npc "I'm concentrating.">>
<<TalkMC "On the course?">>
<<TalkNPC _npc "On both.">>
<<InformationUiPopUp>>I bring my hand to one of her breasts. She keeps going without reacting, one hand jerking me off, the other writing, and me groping her.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate2/3/04.mp4"/>
<<InformationUiPopUp>>I undo the buttons one by one and she doesn't pull away. I hold her, the warmth and weight of her tits, and squeeze gently. She leans forward into my hands and her rhythm shifts, a little more pressure, a little less steady, and she exhales through her nose.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate2/3/05.mp4"/>
<<TalkNPC _npc "Thank you for your help, I wouldn't have believed a few weeks ago that I could improve this much.">>
<<TalkMC "Don't worry about it <<print _npc.name>>, it's normal.">>
<<TalkNPC _npc "But I keep thinking I should be more grateful to you.">>
<<TalkMC "And?">>
<<TalkNPC _npc "And I'm not enough.">>
<video src="assets/img/story/character/mate2/3/06.mp4"/>
<<InformationUiPopUp>>Hearing her say she'd like to thank me even more for my help gives me the urge to push things further with her.
<</InformationUiPopUp>><</revealtext>>
<<revealtext "chapter4">><<InformationUiPopUp "Psychic Power" #7aa2ff>>You decide to use your power on <<=_npc.name>>.<<if _npc.replaytalk == false>>
<em>-1 Psychic Power</em><</if>>
<</InformationUiPopUp>>
<<TalkMC "Listen to my voice.">>
<<TalkMC "Since you absolutely want to thank me, you're going to suck me off as a thank you right now. You're going to love sucking my cock, and it'll feel completely normal to thank me this way.">>
<<TalkNPC _npc "...">>
<<InformationUiPopUp>>She holds my gaze for a long moment. Then something shifts in her expression, more deliberate, decided. She pulls her hand back, stands, and looks at me. She positions herself directly in front of me and then, eyes in mine, she drops to her knees between my legs. Then she starts sucking me, getting on all fours between my legs to thank me as best she can. I take the opportunity to lift her skirt, seeing her ass at the same time while she sucks me. The kitchen is completely quiet around us.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate2/3/07.mp4"/>
<<InformationUiPopUp>>She doesn't rush. She keeps going like she has all the time she needs. I watch her and the afternoon sits completely still around the two of us. The sound she makes is quiet but real.
<</InformationUiPopUp>>
<<TalkNPC _npc "<em>Glrk... mmh... ghlk...</em>">>
<<TalkMC "Mmm... Keep going, I love it.">>
<<InformationUiPopUp>>She picks up her pace gradually, both hands on the floor, her mouth working with more pressure now. I lean back in the chair and let her, resting my hand on her head from time to time to go along with her back and forth.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate2/3/08.mp4"/>
<<TalkNPC _npc "<em>Glrk... mmh...</em>">>
<video src="assets/img/story/character/mate2/3/09.mp4"/>
<<InformationUiPopUp>>I feel it building, and I don't try to slow her down. I signal that I'm going to come, and she responds by sucking harder, until I finish. She takes all my cum in her mouth, staying exactly where she is until it's completely done. She pulls back slowly, wipes the corner of her mouth with the back of her hand, and looks up at me. Her expression is completely normal, like what she just did was the only logical way to thank me.
<</InformationUiPopUp>>
<<TalkNPC _npc "All good?">>
<<TalkMC "Completely. Incredible.">>
<<TalkNPC _npc "You're welcome.">>
<<InformationUiPopUp>>She stands, smooths her skirt and buttons her top back up while I zip up and settle myself. She picks her pen back up from the table and looks at the open notebook, then talks about the last section. Like everything she just did was the most ordinary thing in the world.
<</InformationUiPopUp>>
<<TalkNPC _npc "We never finished the last flag.">>
<<TalkMC "We'll carry on next time?">>
<<TalkNPC _npc "Okay, same time next week then?">>
<<TalkMC "Works for me.">>
<<InformationUiPopUp>>She nods and goes back to writing in her notebook, calm and unhurried.
<</InformationUiPopUp>><</revealtext>>
/* ====================================================
*
* ----------------------------------- CHAPTER 5 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 4>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><<set $FromOtherPlace = true>><<set $ReturnTo = "ApartmentsInside">><</if>>
<<passagebg>><<sound "bg" "bg.universityGymnasium" true>><img src="assets/img/misc/university/gymnasium.webp"/><</passagebg>>
<<InformationUiPopUp>>Outside the university gymnasium, afternoon. The session just ended and students are filing out around us. <<print _npc.name>> is waiting near the wall, already changed. She spots me and steps forward before I reach her.
<</InformationUiPopUp>>
<<TalkNPC _npc "Hey, got a minute?">>
<<TalkMC "Yep, what's up?">>
<<TalkNPC _npc "Would you be free to train with me again today? At mine.">>
<<TalkMC "We just finished a session.">>
<<TalkNPC _npc "I know, but I'm still not totally comfortable with some of the exercises.">>
<<TalkMC "Mmm...">>
<<TalkNPC _npc "If you're free obviously?">>
<<TalkMC "Yeah, okay, sure, works for me.">>
<<TalkNPC _npc "Thank you.">>
<<InformationUiPopUp>>We walk off campus together. The route is completely familiar now. We arrive at her building, go up, and she opens the door for me.
<</InformationUiPopUp>>
<<revealtext "enter">><<passagebg>><img src="assets/img/misc/city/apartments/bedroommate2.webp"/><</passagebg>><<InformationUiPopUp>>We head through to the living room. She sets her bag down and looks at me.
<</InformationUiPopUp>>
<<TalkNPC _npc "I'm going to get changed, give me two minutes.">>
<<TalkMC "Take your time.">>
<<TalkNPC _npc "Thank you.">>
<<InformationUiPopUp>>She disappears down the hall. I think through a warm-up sequence. On the way over she told me she bought a jump rope to train with.
<</InformationUiPopUp>>
<<InformationUiPopUp>>She comes back in her sports top and shorts, hair pulled back. We start with the warm-up, her form noticeably cleaner than the first time, self-correcting before I say anything.
<</InformationUiPopUp>>
<<TalkMC "You've been practicing on your own?">>
<<TalkNPC _npc "I kept thinking about what you said about the arms leading everything. I wanted to get it right.">>
<<TalkMC "So it worked?">>
<<TalkNPC _npc "It worked, like you said.">>
<<TalkMC "Nice.">>
<<TalkNPC _npc "Can we do the rope now?">>
<<TalkMC "Yeah, show me.">>
<<TalkNPC _npc "Okay.">>
<<InformationUiPopUp>>She goes to her bag and pulls out the rope. She positions herself in the center of the space and starts. Her timing is slightly off at first, then she finds the rhythm. The top shifts immediately and within a few seconds her tits are completely out, bare, moving with every jump. She doesn't stop. Her expression stays focused on her timing like she's simply doing the exercise.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate2/4/01.mp4"/>
<<TalkNPC _npc "Is it... is it okay? What I'm doing.">>
<<TalkMC "It just needs practice, but you don't have to worry, it'll come with time.">>
<<TalkNPC _npc "Thank you.">>
<video src="assets/img/story/character/mate2/4/02.mp4"/>
<<InformationUiPopUp>>She keeps going for a good minute, then slows and stops. She's breathing harder, chest rising and falling, still completely out of the top. She looks at me, then drops her gaze lower, and her expression shifts.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate2/4/03.mp4"/>
<<TalkNPC _npc "<<print $MCPlayer.firstname>>.">>
<<TalkMC "Yeah?">>
<<TalkNPC _npc "I can see that... I mean, your trousers.">>
<<TalkNPC _npc "I'm sorry, I didn't mean to... well, I did, but...">>
<<TalkMC "Don't be sorry.">>
<<TalkNPC _npc "Do you want me to thank you now?">>
<<TalkMC "Why not... Just before that, let me do something first.">>
<<InformationUiPopUp>>Seeing her tits bounce like that this whole time has just got to me. I sit down on the couch and tell her to sit in front of me so I can be right behind her. She does it, her head tilting slightly forward. I put my hands on her bare tits and squeeze them, feeling them fully in my palms.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate2/4/04.mp4"/>
<<TalkMC "I love your huge tits, they feel so good.">>
<<TalkNPC _npc "Thank you.">>
<<TalkMC "You don't have to thank me, you're the one thanking me by letting me grope you.">>
<<TalkNPC _npc "I know, I just wanted to.">>
<<InformationUiPopUp>>I stretch my arms out and cover her tits completely, pressing harder, like I'm simply playing with them.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate2/4/05.mp4"/>
<<TalkMC "Here, you're going to lick your tits with me.">>
<<InformationUiPopUp>>I hold her tits in my hands and bring one of them toward her mouth. She licks it slowly and deliberately, while I do the same with the other one.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate2/4/06.mp4"/>
<<TalkNPC _npc "<em>Mmh... ah...</em>">>
<<TalkMC "You like that?">>
<<TalkNPC _npc "Yes, even though I'm supposed to be the one thanking you, I feel like I'm the one getting the most out of this...">>
<<TalkMC "Don't worry about that, I have an idea of how you could really thank me.">>
<<TalkNPC _npc "Mmm... You want me to suck you off?">><</revealtext>>
<<revealtext "chapter5">><<InformationUiPopUp "Psychic Power" #7aa2ff>>You decide to use your power on <<=_npc.name>>.<<if _npc.replaytalk == false>>
<em>-1 Psychic Power</em><</if>>
<</InformationUiPopUp>>
<<TalkMC "Listen to me.">>
<<TalkMC "Since you think I'm not getting enough pleasure, you're going to let me fuck you. That'll be your new way of thanking me for helping you, on top of the other ways.">>
<<TalkNPC _npc "...">>
<<InformationUiPopUp>>Her breathing shifts and she looks at me.
<</InformationUiPopUp>>
<<TalkNPC _npc "You know... <<print $MCPlayer.firstname>>... I really want to thank you in the best possible way...">>
<<InformationUiPopUp>>She heads over to the couch on her own and gets on all fours, her ass in the air, her pussy wide open, looking back at me over her shoulder, waiting for nothing but my cock inside her. I pull my shorts down and when I push into her she makes a long sound that fills the entire apartment.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate2/4/07.mp4"/>
<<TalkNPC _npc "<em>Ah... mmh... yes...</em>">>
<<TalkNPC _npc "You like it?">>
<<TalkMC "Oh yes, I love it.">>
<<InformationUiPopUp>>I find a rhythm and she takes my cock completely, her hands gripping the armrest.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate2/4/08.mp4"/>
<<TalkNPC _npc "Don't stop, please, don't stop...">>
<<TalkMC "I have no intention of stopping.">>
<<InformationUiPopUp>>Her sounds become continuous and unbroken. She takes everything without pulling back, without asking me to slow down.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate2/4/09.mp4"/>
<<InformationUiPopUp>>I slow deliberately and she makes a small desperate sound at the change, her hips pressing back trying to keep the pace.
<</InformationUiPopUp>>
<<TalkNPC _npc "Please, don't...">>
<<TalkMC "I'll remind you that you're the one who's supposed to be thanking me. I'm doing all the work here, so I want to change position.">>
<<TalkNPC _npc "Oh. Okay, obviously, whatever you want.">>
<<TalkMC "I'm going to lie down, and you get on top and do all the work.">>
<<TalkNPC _npc "Okay, that works for me.">>
<<InformationUiPopUp>>I lie down on the couch, then she repositions herself immediately, sitting on top of me facing away. The sound she makes when my cock pushes into her pussy is sharp and immediate. She stays still, waiting for me to set the pace.
<</InformationUiPopUp>>
<<TalkMC "I already told you, you're the one who moves.">>
<<TalkNPC _npc "Yes, sorry.">>
<video src="assets/img/story/character/mate2/4/10.mp4"/>
<<InformationUiPopUp>>She moves at her own rhythm, her sounds building with every thrust.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate2/4/11.mp4"/>
<<TalkNPC _npc "<em>Ah... fuck... more...</em>">>
<<TalkNPC _npc "<<print $MCPlayer.firstname>>.">>
<<TalkMC "Mmm?">>
<<TalkNPC _npc "Thank you, I know it's not really my place to thank you right now, but I'm getting so much out of this too...">>
<<TalkMC "Don't mention it, I'm getting just as much pleasure, so don't stop.">>
<<InformationUiPopUp>>After a while I grow tired of her rhythm. I put my hands on her hips and take complete control, lifting her legs toward her and pushing up from below.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate2/4/12.mp4"/>
<<TalkNPC _npc "<em>Ah... yes... fuck...</em>">>
<<TalkNPC _npc "Oh God, oh, please...">>
<<TalkMC "I got tired of it, you were too slow.">>
<<TalkNPC _npc "Sorry, I'm sorry, but please don't stop, please.">>
<<InformationUiPopUp>>I keep the pace hard, her cries of pleasure filling the room.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate2/4/13.mp4"/>
<<TalkNPC _npc "<em>Ah... mmh... I'm going to come...</em>">>
<<TalkNPC _npc "Right there. Please, right there, there...">>
<<TalkMC "I've got you.">>
<<TalkNPC _npc "Please, please.">>
<<InformationUiPopUp>>Her legs are shaking and I push harder, holding her exactly where I want her.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate2/4/14.mp4"/>
<<TalkNPC _npc "I'm going to... I'm going to, please don't stop...">>
<<TalkMC "Go ahead, let yourself go completely.">>
<<TalkNPC _npc "Yes, thank you, thank you!">>
<<TalkNPC _npc "<em>Ah... ah... yes... yes...</em>">>
<<TalkMC "Good. But I'm not done, so we keep going.">>
<<TalkNPC _npc "Of course...">>
<<InformationUiPopUp>>She finishes, legs still trembling. I let her come down for a moment, then after a while she lifts herself off and turns to face me, still above me.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate2/4/15.mp4"/>
<<InformationUiPopUp>>She moves at the rhythm I give her, her eyes staying on mine, her expression unguarded and entirely focused on me. There's nothing left in her that holds back, nothing that hesitates.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate2/4/16.mp4"/>
<<TalkMC "You're incredible.">>
<<TalkNPC _npc "Thank you.">>
<<InformationUiPopUp>>Her pace builds under my hands on her hips and her cries of pleasure return, continuous and open.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate2/4/17.mp4"/>
<<TalkNPC _npc "<em>Ah... mmh... more...</em>">>
<<TalkNPC _npc "<<print $MCPlayer.firstname>>.">>
<<TalkMC "Yeah?">>
<<TalkNPC _npc "I'm close again, does that bother you?">>
<<TalkMC "Let's change position then, let me take over.">>
<<TalkNPC _npc "Okay.">>
<<InformationUiPopUp>>I flip us over and she lands on her back, staying exactly where I put her, eyes up at me, her legs wide open, waiting for nothing but me.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate2/4/18.mp4"/>
<<TalkNPC _npc "<<print $MCPlayer.firstname>>.">>
<<TalkMC "Mmm?">>
<<TalkNPC _npc "Please don't hold back.">>
<<TalkMC "I'm not holding back.">>
<<TalkNPC _npc "Please, give me everything.">>
<<TalkMC "Take it then.">>
<<InformationUiPopUp>>She takes everything I give her, her hands gripping the couch, while I pound her pussy.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate2/4/19.mp4"/>
<<TalkNPC _npc "<em>Ah... yes... fuck...</em>">>
<<TalkNPC _npc "Please, like that, please don't stop...">>
<<InformationUiPopUp>>Her sounds peak and her whole body responds completely, nothing held back.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate2/4/20.mp4"/>
<<TalkNPC _npc "<em>Ah... ah... yes... yes...</em>">>
<<InformationUiPopUp>>The rhythm becomes less controlled and I can feel I'm going to come soon. I pull out in a rush. She understands and lifts her upper body quickly, barely in time. I finish aiming at her face and chest. I exhale hard and stay above her. The living room is completely still and warm.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate2/4/21.mp4"/>
<<TalkNPC _npc "Was it... was it good?">>
<<TalkMC "Very. Really good.">>
<<TalkNPC _npc "Good, I wanted to thank you in the best possible way, to make it good for you.">>
<<TalkMC "It was.">>
<<InformationUiPopUp>>She finally looks up at me, waiting to see what I want next.
<</InformationUiPopUp>>
<<TalkMC "Same time next week?">>
<<TalkNPC _npc "Yes, whenever you want.">>
<<TalkMC "Okay, see you next week then.">>
<<TalkNPC _npc "Thank you... For today, for everything.">>
<<TalkMC "Don't thank me.">>
<<TalkNPC _npc "I can't help it.">><</revealtext>>
/* ====================================================
*
* ----------------------------------- CHAPTER 6 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 5>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><<set $FromOtherPlace = true>><<set $ReturnTo = "BedroomMate2">><</if>>
<<passagebg>><<sound "bg" "bg.universityGymnasium" true>><img src="assets/img/misc/university/gymnasium.webp"/><</passagebg>>
<<InformationUiPopUp>>After receiving a message from her asking me to meet her at the university gymnasium this afternoon, she was waiting for me after her session.
<</InformationUiPopUp>>
<<TalkMC "Have you been waiting long?">>
<<TalkNPC _npc "Ah, no, don't worry, we literally just finished.">>
<<TalkMC "Okay. You wanted to see me?">>
<<TalkNPC _npc "Yes, I wanted to know if you'd like to come over to mine, to carry on with the courses?">>
<<TalkMC "Mmm...">>
<<InformationUiPopUp>>I'd love for her to invite me over without needing this excuse of courses or sport. And given how the last training session ended, I think this would be the perfect moment to make her completely mine.
<</InformationUiPopUp>>
<<TalkMC "Will your parents be there?">>
<<TalkNPC _npc "No, the apartment is mine. The other times my parents came it was just to visit. But now I've asked them to get my agreement before coming over, or at least let me know in advance.">>
<<InformationUiPopUp>>That's exactly what I thought. This is the perfect moment to finalize things with her. Make her completely submissive to me.
<</InformationUiPopUp>>
<<revealtext "chapter6">><<InformationUiPopUp "Psychic Power" #7aa2ff>>You decide to use your power on <<=_npc.name>>.<<if _npc.replaytalk == false>>
<em>-1 Psychic Power</em><</if>>
<</InformationUiPopUp>>
<<TalkMC "Listen to me.">>
<<InformationUiPopUp>>I lower my voice to be discreet and not draw attention.
<</InformationUiPopUp>>
<<TalkMC "You are going to be completely submissive from now on. I'll be able to come see you anytime, anywhere, and you will be totally at my service. Your body will be mine, I'll be able to use you however I please, and you will love it. It won't just be to thank me for my help anymore, it will be far more than that, an adoration, a total submission. You will do everything I order you to. And from now on you will call me Master when we are alone.">>
<<TalkNPC _npc "...">>
<<InformationUiPopUp>>She stays blank-eyed for a few seconds, the time it takes for the order to fully sink into her. Then she comes back to herself and looks at me with a lot of desire and submission.
<</InformationUiPopUp>>
<<TalkNPC _npc "Mas... Master.">>
<<TalkNPC _npc "...Forget the courses actually.">>
<<TalkNPC _npc "But you'll still come over to mine?">>
<<TalkMC "Mmm... And what would we do if not the courses?">>
<<TalkNPC _npc "You... you could have me...">>
<<TalkMC "I like that. Let's go then.">>
<<InformationUiPopUp>>After a few minutes walking to her apartment, we arrive outside, then she opens the door for me.
<</InformationUiPopUp>><</revealtext>>
<<revealtext "enter">><<passagebg>><img src="assets/img/misc/city/apartments/bedroommate2.webp"/><</passagebg>><<InformationUiPopUp>>She lets me in and tells me to wait, that she's going to shower first. The bathroom door is ajar and I can hear the water running. I stay sitting for about two minutes before I stop pretending to wait here.
<</InformationUiPopUp>>
<<TalkMC "<em>Why am I waiting here? I want to see her naked body, right now.</em>">>
<<InformationUiPopUp>>I undress quietly, leave my clothes on the floor, and stay there for a moment listening to the water. Then I push the bathroom door open gently, hiding to watch her completely naked.
<</InformationUiPopUp>>
<<InformationUiPopUp>>The shower glass is slightly fogged. She's completely visible through it, slightly turned toward me, her hair wet, the water running down her. She hasn't heard me come in.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate2/5/01.mp4"/>
<<InformationUiPopUp>>I watch her for a moment without moving. She bends down slightly, reaching for something on the floor to scrub herself with, her profile visible through the glass.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate2/5/02.mp4"/>
<<InformationUiPopUp>>She rinses off and the water runs down the full length of her body.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate2/5/03.mp4"/>
<<InformationUiPopUp>>I can't wait any longer and decide to step into the shower. She turns immediately at the sound, eyes wide for one second, then her expression shifts from surprise to something warm and immediate.
<</InformationUiPopUp>>
<<TalkNPC _npc "Oh! Master! I didn't hear you, I was almost done.">>
<<TalkMC "I know.">>
<<TalkNPC _npc "I'm sorry, I didn't mean to take so long.">>
<<TalkMC "You were here. Naked. I couldn't let that go.">>
<<TalkNPC _npc "I'm sorry, Master.">>
<video src="assets/img/story/character/mate2/5/04.mp4"/>
<<InformationUiPopUp>>We stand in the shower together. She looks up at me, waiting for me to tell her what I want. The water is warm and the bathroom is steamed.
<</InformationUiPopUp>>
<<TalkMC "I want you to do something for me.">>
<<TalkNPC _npc "Whatever you want, Master. Whatever you want.">>
<<TalkMC "Get on your knees and suck me.">>
<<TalkNPC _npc "Yes, Master.">>
<<InformationUiPopUp>>She drops down without hesitation, takes my cock in her mouth, eyes up at me.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate2/5/05.mp4"/>
<<TalkNPC _npc "<em>Glrk... mmh... ghlk...</em>">>
<<InformationUiPopUp>>She works with both hands and her mouth, her rhythm entirely focused on me, on her task, seeking only to satisfy my order.
<</InformationUiPopUp>>
<<TalkMC "Wait.">>
<<TalkNPC _npc "Yes, Master?">>
<<TalkMC "Let me do it.">>
<<TalkNPC _npc "Yes, Master. I'm sorry.">>
<<InformationUiPopUp>>She keeps sucking while I take her head in my hands to impose my rhythm.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate2/5/06.mp4"/>
<<TalkNPC _npc "<em>Glrk... mmh... ghlk...</em>">>
<<TalkMC "Good. Get up now.">>
<<TalkNPC _npc "Yes, Master.">>
<<TalkMC "And turn around, I'm going to fuck your pussy.">>
<<InformationUiPopUp>>She stands and turns, leans forward and places both hands flat against the shower wall, her back to me. Her head tilts slightly forward, waiting for my cock inside her.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate2/5/07.mp4"/>
<<TalkMC "Good girl.">>
<<TalkNPC _npc "Thank you, Master.">>
<<InformationUiPopUp>>She stays still, taking the rhythm I set, her sounds of pleasure mixing with the noise of the water.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate2/5/08.mp4"/>
<<TalkNPC _npc "<em>Ah... mmh... yes...</em>">>
<<InformationUiPopUp>>After a few minutes, I tell her to take me to her bedroom.
<</InformationUiPopUp>>
<<TalkMC "Show me your bedroom.">>
<<TalkNPC _npc "Yes, Master, of course.">>
<<InformationUiPopUp>>We don't bother drying off completely. She walks ahead of me and lies back on the bed without being asked, eyes up at me.
<</InformationUiPopUp>>
<<TalkNPC _npc "How do you want to fuck me, Master?">>
<<TalkMC "Stay exactly like that.">>
<<InformationUiPopUp>>I lift one of her legs immediately, pressing it along my body as I push my cock into her. The angle changes everything and she makes a sound that fills the bedroom completely.
<</InformationUiPopUp>>
<<TalkNPC _npc "<em>Ah... mmh... fuck...</em>">>
<<TalkNPC _npc "Master, it's...">>
<<TalkMC "Shhhh.">>
<<TalkNPC _npc "Please don't stop, please.">>
<<TalkMC "Don't worry about that. But I want to watch you lick your tits for me.">>
<<TalkNPC _npc "Yes, Master, whatever you want.">>
<video src="assets/img/story/character/mate2/5/09.mp4"/>
<<InformationUiPopUp>>I find a rhythm and she licks her tits, her leg pressed against me, the angle letting me fuck her deeper and more directly. Her sounds are constant now, unbroken, and she takes everything without pulling away.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate2/5/10.mp4"/>
<<TalkNPC _npc "<em>Ah... yes... more...</em>">>
<<TalkNPC _npc "Master. Master, please...">>
<<TalkMC "Please what?">>
<<TalkNPC _npc "Don't stop, please don't stop, please, Master.">>
<<InformationUiPopUp>>I decide to release her leg, letting her take over. Her sounds peak and I push harder.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate2/5/11.mp4"/>
<<TalkNPC _npc "Right there. Right there, Master, please...">>
<<TalkNPC _npc "Please. Please don't stop.">>
<<TalkMC "Let yourself go completely.">>
<<TalkNPC _npc "Thank you. Thank you, Master.">>
<<InformationUiPopUp>>I slow down and she comes down gradually, breathing hard. She looks up at me, her expression completely open, with a particular idea in mind.
<</InformationUiPopUp>>
<<TalkNPC _npc "Master...">>
<<TalkMC "Yeah?">>
<<TalkNPC _npc "Can I... may I be on top? If you want.">>
<<TalkMC "Go ahead.">>
<<TalkNPC _npc "Yes, Master. Thank you.">>
<<InformationUiPopUp>>I lie back and she positions herself carefully on top of me, turning her face to look back, making sure of the rhythm.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate2/5/12.mp4"/>
<<TalkMC "Look at me.">>
<<TalkNPC _npc "Yes, Master.">>
<<TalkMC "Good little slut.">>
<<InformationUiPopUp>>She moves at the rhythm I give her through my hands on her hips, her eyes staying on mine, her expression completely unguarded and entirely focused on me.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate2/5/13.mp4"/>
<<TalkNPC _npc "<em>Ah... mmh... yes...</em>">>
<<TalkNPC _npc "Master, I love you so much.">>
<<InformationUiPopUp>>She stays exactly where she is, not stopping until I slow her down.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate2/5/14.mp4"/>
<<TalkNPC _npc "<em>Ah... fuck... more...</em>">>
<<TalkNPC _npc "Master, it's so good.">>
<<TalkMC "Turn over.">>
<<TalkNPC _npc "Yes, Master.">>
<<InformationUiPopUp>>She lifts off me and turns onto all fours immediately, back arched, head down, leaving her ass completely open, waiting for nothing but me. I position myself behind her and push my cock back into her and she makes a long low sound into the bed.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate2/5/15.mp4"/>
<<TalkNPC _npc "<em>Ah... mmh... yes...</em>">>
<<InformationUiPopUp>>I build the pace and she braces herself, taking everything I give her, her sounds intensifying with every increase.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate2/5/16.mp4"/>
<<TalkNPC _npc "<em>Ah... fuck... more...</em>">>
<<TalkNPC _npc "Please, Master. Harder. Please.">>
<<InformationUiPopUp>>Her sounds fill the bedroom completely, unbroken, intensifying with every increase. I put one hand on her hip and hold her exactly where I want her and she stays perfectly in place.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate2/5/17.mp4"/>
<<TalkNPC _npc "<em>Ah... yes... fuck...</em>">>
<<TalkNPC _npc "Don't stop. Master, please don't stop. Please.">>
<<TalkMC "You really love this, slut.">>
<<TalkNPC _npc "Yes, I love it, Master.">>
<<InformationUiPopUp>>I keep the pace relentless, she takes everything without pulling away, the sound of my thighs slapping against her ass.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate2/5/18.mp4"/>
<<TalkNPC _npc "<em>Ah... mmh... I'm going to come...</em>">>
<<TalkNPC _npc "Master, I... please...">>
<<TalkMC "Not yet.">>
<<TalkNPC _npc "Yes, Master.">>
<<TalkMC "Good girl.">>
<<TalkNPC _npc "Thank you, Master. Thank you.">>
<video src="assets/img/story/character/mate2/5/19.mp4"/>
<<TalkNPC _npc "<em>Ah... yes... please...</em>">>
<<TalkNPC _npc "Master, I love your cock so much, take me like the slut I am.">>
<<InformationUiPopUp>>I reach forward and grab both her arms, pulling her upright against my chest, continuing without breaking the rhythm. She lets out cries of pleasure at the change in angle, her arms held, completely open and unable to do anything but take my cock.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate2/5/20.mp4"/>
<<TalkNPC _npc "<em>Ah... ah... yes... yes...</em>">>
<<InformationUiPopUp>>She ends up coming while I hold her there for a long moment, then I slow and let her go. She collapses forward onto the bed, breathing hard, then at the same time as I stand up, she turns over and slowly sits up, eyes up at me. She already knows what I want and gets into position without being told.
<</InformationUiPopUp>>
<<TalkNPC _npc "Master, come all over me, please.">>
<<TalkMC "Keep your eyes open.">>
<<TalkNPC _npc "Yes, Master. I want it all. I want all your love.">>
<<InformationUiPopUp>>She stays on her knees on the bed, holding her tits in her hands and making them bounce to make me want to come on her, eyes up at me with a completely submissive expression, waiting for my cum.
<</InformationUiPopUp>>
<<InformationUiPopUp>>I finish on her face and her tits, and she stays exactly where she is, opening her mouth wide to catch as much as possible.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate2/5/21.mp4"/>
<<TalkNPC _npc "Master.">>
<<TalkMC "Mmm?">>
<<TalkNPC _npc "Did you like it? Was I good?">>
<<TalkMC "Very. You were an excellent slut.">>
<<TalkNPC _npc "Thank you. I'm really happy to be able to serve you. I wanted so much to do right by you.">>
<<TalkMC "You did.">>
<<TalkNPC _npc "You... do you want to stay tonight? You don't have to, just... I'd like you to stay.">>
<<TalkMC "Let me rest, and I'll see.">>
<<TalkNPC _npc "Really?">>
<<TalkMC "Yes.">>
<<TalkNPC _npc "Thank you, Master.">>
<<InformationUiPopUp>>She grabs a tissue from the nightstand, cleans herself quietly, then stays naked beside me, her eyes on me with a lot of love and submission in her gaze, waiting for my next order.
<</InformationUiPopUp>><</revealtext>>
/* ====================================================
*
* -------------------------------- REPLAY CHAPTER --------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl > 5>><<set $SaveTalklvl = _npc.talklvl>><<set _npc.replaytalk = true>><<set _gotoReplayNpc = "Talk." + _npc.id>>
<<passagebg>><img src="assets/background.gif"/><</passagebg>>
<style>.rCard a{display:flex;align-items:center;gap:clamp(6px,1vw,10px);padding:clamp(8px,1.2vw,11px) clamp(10px,1.5vw,16px);border-radius:10px;background:rgba(230,87,99,.07);border:1px solid rgba(230,87,99,.18);text-decoration:none;transition:background .15s;}.rCard a:hover{background:rgba(230,87,99,.14);border-color:rgba(230,87,99,.35);}.rCard .rNum{font-size:calc(clamp(14px,1.8vw,18px) + var(--font-boost,0px));font-weight:950;color:rgba(255,255,255,.92);}.rCard .rLabel{font-size:calc(clamp(9px,1vw,12px) + var(--font-boost,0px));font-weight:900;letter-spacing:.16em;text-transform:uppercase;color:rgba(230,87,99,.55);}.rCard .rArrow{margin-left:auto;font-size:calc(clamp(9px,1vw,12px) + var(--font-boost,0px));font-weight:900;letter-spacing:.1em;color:rgba(230,87,99,.45);}</style><div style="display:flex;flex-direction:column;gap:6px;width:100%;margin-top:6px;"><div style="font-size:calc(clamp(9px,1vw,12px) + var(--font-boost,0px));font-weight:900;letter-spacing:.16em;text-transform:uppercase;color:rgba(255,255,255,.18);margin-bottom:6px;text-align:center;">— Select a scene to replay —</div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>01</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 0>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>02</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 1>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>03</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 2>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>04</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 3>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>05</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 4>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>06</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 5>><<goto _gotoReplayNpc>><</link>></div></div>
<</if>><</if>><div class="BottomUiBarCustom">
<<if _npc.talklvl == 0>><<BottomButton "Decision">><<revealbtn "chapter1" "🧠 Use power" "" "powerid" "enterid" true>><<UsePsychicPower>><</revealbtn>><<revealbtn "enter" "➡️ Enter" "moveBtn" "enterid" "" false>><<bgpause>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 1>><<BottomButton "Decision">><<revealbtn "enter" "➡️ Enter" "" "enterid" "powerid" true>><<bgpause>><</revealbtn>><<revealbtn "chapter2" "🧠 Use power" "moveBtn" "powerid" "" false>><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 2>><<BottomButton "Decision">><<revealbtn "enter" "➡️ Enter" "" "enterid" "powerid" true>><<bgpause>><</revealbtn>><<revealbtn "chapter3" "🧠 Use power" "moveBtn" "powerid" "" false>><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 3>><<BottomButton "Decision">><<revealbtn "enter" "➡️ Enter" "" "enterid" "powerid" true>><<bgpause>><</revealbtn>><<revealbtn "chapter4" "🧠 Use power" "moveBtn" "powerid" "" false>><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 4>><<BottomButton "Decision">><<revealbtn "enter" "➡️ Enter" "" "enterid" "powerid" true>><<bgpause>><</revealbtn>><<revealbtn "chapter5" "🧠 Use power" "moveBtn" "powerid" "" false>><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 5>><<BottomButton "Decision">><<revealbtn "chapter6" "🧠 Use power" "" "powerid" "enterid" true>><<UsePsychicPower>><</revealbtn>><<revealbtn "enter" "➡️ Enter" "moveBtn" "enterid" "" false>><<bgpause>><</revealbtn>><</BottomButton>><</if>>
<<BottomButton "Move" "moveBtn">><<if $FromOtherPlace == true>><<link "↩️ Return">><<if _npc.replaytalk == false>><<set _npc.talklvl++>><<set _npc.lvl++>><<set $PsychicPower -= 1>><<if _NextTime == true>><<set $Time++>><<set _NextTime = false>><</if>><<else>><<set _npc.talklvl = $SaveTalklvl>><<set _npc.replaytalk = false>><</if>><<ReturnToGoto>><<set $FromOtherPlace = false>><</link>><<else>><<link "↩️ Return">><<if _npc.replaytalk == false>><<set _npc.talklvl++>><<set _npc.lvl++>><<set $PsychicPower -= 1>><<if _NextTime == true>><<set $Time++>><<set _NextTime = false>><</if>><<else>><<set _npc.talklvl = $SaveTalklvl>><<set _npc.replaytalk = false>><</if>><<bgpause>><<goto _gotoNpc>><</link>><</if>><</BottomButton>>
</div><<sound "music" "music.music" true>><<set _raw = $ActiveNPC>><<if !_raw or _raw.id is undefined>>Invalid NPC.<<else>><<set _id = String(_raw.id)>><<set _key = "NPC" + _id>><<run State.temporary.npcObj = State.variables[State.temporary.key] || State.variables[_key]>><<set _npc = _npcObj>><<set _gotoNpc = _npc.id + ".interact">>
/* ====================================================
*
* ----------------------------------- CHAPTER 1 -----------------------------------------
*
*/ ====================================================
<<if _npc.talklvl == 0>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><</if>>
<<passagebg>><<sound "bg" "bg.classroom" true>><img src="assets/img/misc/university/class1.webp"/><</passagebg>>
<<InformationUiPopUp>>Early morning, the air is still cool. Students stream toward Amphitheater 1, backpacks over their shoulders. The entrance is a bottleneck of tired faces and half-awake conversations.
<</InformationUiPopUp>>
<<InformationUiPopUp>>She's standing just to the side of the crowd, waiting for the flow to thin before heading in, scrolling through her phone with one hand. I've crossed paths with her before, in passing, but never spoken to her. Today, for whatever reason, I decide that's going to change.
<</InformationUiPopUp>>
<<TalkMC "Hey, sorry to bother you. First time in Amphi 1?">>
<<TalkNPC _npc "Hm?">>
<<InformationUiPopUp>>She looks up from her phone, mildly surprised.
<</InformationUiPopUp>>
<<TalkNPC _npc "Oh. No, I've had lectures here before, why?">>
<<TalkMC "Just making conversation while the crowd thins out. I'm <<print $MCPlayer.firstname>>, by the way.">>
<<TalkNPC _npc "<<print _npc.name>>.">>
<<InformationUiPopUp>>She says it simply, no coldness either. She tucks her phone into her jacket pocket and, once the crowd has spread out enough, follows the flow toward the doors. I match her pace, keeping up to continue the conversation.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate3/0/01.mp4"/>
<<TalkMC "What are you here for? The nine o'clock?">>
<<TalkNPC _npc "Introduction to Social Psychology. You?">>
<<TalkMC "Same, actually.">>
<<TalkNPC _npc "Hm.">>
<<InformationUiPopUp>>Not exactly an enthusiastic response. But she didn't walk away either, which I decide to count as a small victory.
<</InformationUiPopUp>>
<<TalkMC "You don't look thrilled.">>
<<TalkNPC _npc "No, it's not that. It's just that I had to get up at seven to catch the bus, and the bus was late, so I'm running on about four hours of sleep and one coffee that was nowhere near strong enough.">>
<<TalkMC "That sounds like a rough morning.">>
<<TalkNPC _npc "It's the morning. Every morning is rough.">>
<<TalkMC "Fair enough.">>
<<InformationUiPopUp>>We reach the double doors. A small group ahead of us bunches up, then the doors finally clear. We push through into the building and the ambient noise shifts from open-air chatter to the hollow echo of a high-ceilinged corridor. The amphitheater entrance is just ahead, the double doors already propped open, a few students filing in.
<</InformationUiPopUp>>
<<TalkMC "What made you choose this course? It's not exactly the most obvious pick.">>
<<TalkNPC _npc "I wanted to understand something and this was the closest program to what I was looking for.">>
<<TalkMC "Understand what?">>
<<InformationUiPopUp>>She slows slightly, a small hesitation, like the question caught her slightly off guard despite not being particularly invasive.
<</InformationUiPopUp>>
<<TalkNPC _npc "Why people make the choices they do. Especially when those choices go against what they claim to want. The gap between stated values and actual behavior. That kind of thing.">>
<<TalkMC "That's... oddly specific.">>
<<TalkNPC _npc "Is it? Most people have a reason they chose their field. Usually something personal.">>
<<TalkMC "I suppose. Mine was just that I had no idea what I wanted and this seemed like a way to buy myself time to figure it out.">>
<<TalkNPC _npc "At least you're honest about it.">>
<<TalkMC "Most people aren't?">>
<<TalkNPC _npc "Most people I talk to in this building tell me they've always had a passion for their subject since age twelve. Which I find statistically unlikely.">>
<<InformationUiPopUp>>We kept talking for a little while longer before stepping into the amphitheater itself. The room is large, steeply tiered, already about a third full with students spreading out across the rows.
<</InformationUiPopUp>>
<<TalkMC "I'm not really sure where to sit...">>
<<TalkNPC _npc "Personally, I usually sit somewhere in the middle.">>
<<InformationUiPopUp>>She starts making her way up the left aisle, scanning the rows as she goes. I walk with her a few more steps, enough to feel natural, before peeling off.
<</InformationUiPopUp>>
<<TalkMC "I'll probably go a bit higher up. Habit.">>
<<TalkNPC _npc "Okay.">>
<<InformationUiPopUp>>There's a brief pause. Neither of us really says goodbye.
<</InformationUiPopUp>>
<<TalkMC "Mmm... Could I get your number? So we could carry on the conversation later.">>
<<TalkNPC _npc "...">>
<<InformationUiPopUp>>I can tell from her look that she's hesitating. I'd like to get a bit closer to her, and I can make sure that happens.
<</InformationUiPopUp>>
<<revealtext "chapter1">><<InformationUiPopUp "Psychic Power" #7aa2ff>>You decide to use your power on <<=_npc.name>>.<<if _npc.replaytalk == false>>
<em>-1 Psychic Power</em><</if>>
<</InformationUiPopUp>>
<<TalkMC "Listen to me.">>
<<InformationUiPopUp>>I move closer to her, lowering my voice to stay discreet.
<</InformationUiPopUp>>
<<TalkMC "You're going to give me your number. You enjoyed my company and you'll want to see me again.">>
<<TalkNPC _npc "...">>
<<InformationUiPopUp>>After a few seconds of blankness, she gives me her answer.
<</InformationUiPopUp>>
<<TalkNPC _npc "Sure, no problem, I enjoyed talking to you.">>
<<InformationUiPopUp>>She holds out her hand, signaling me to hand over my phone. Once I get it back, I can see her number saved in my contacts.
<</InformationUiPopUp>>
<<TalkNPC _npc "I added you in my contacts too.">>
<<TalkMC "Nice.">>
<<TalkNPC _npc "Well then, see you around, <<print $MCPlayer.firstname>>.">>
<<TalkMC "See you around.">>
<<InformationUiPopUp>>She finds a row she's happy with and slides in, dropping her bag under the seat and pulling out a notebook. I head up a few more rows and take a seat with a clear view of the board.
<</InformationUiPopUp>>
<<InformationUiPopUp>>The room fills gradually around me. Down below I can see <<print _npc.name>> opening her notebook, already looking toward the projector screen. I think about the conversation we just had. It wasn't remarkable by any objective standard, but thanks to my power, we'll stay in touch at least.
<</InformationUiPopUp>>
<<InformationUiPopUp>>At the front, the professor sets down her bag and the room begins to settle. The morning carried on.
<</InformationUiPopUp>><</revealtext>>
/* ====================================================
*
* ----------------------------------- CHAPTER 2 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 1>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><<set $FromOtherPlace = true>><<set $ReturnTo = "City">><</if>>
<<passagebg>><<sound "bg" "bg.university" true>><img src="assets/img/misc/university/university.webp"/><</passagebg>>
<<InformationUiPopUp>>It's around noon. The lecture in Amphitheater 2 has just wrapped up, and the room is emptying in the usual slow shuffle of students gathering notes and zipping bags. I'm not in a rush. Neither is <<print _npc.name>>, apparently, still sitting two rows over, turning her phone over in her hand like she's waiting for something. She turns around and signals to me.
<</InformationUiPopUp>>
<<TalkNPC _npc "Hey. Quick question.">>
<<TalkMC "Go ahead.">>
<<TalkNPC _npc "You have a car?">>
<<TalkMC "Yeah.">>
<<TalkNPC _npc "Any chance you're heading toward the city center after this?">>
<<TalkMC "I can be. You need a lift?">>
<<TalkNPC _npc "If it's not too much to ask. The tram line is suspended until tonight because of some maintenance thing and I really don't feel like waiting.">>
<<TalkMC "No problem, I'm parked in the lot.">>
<<TalkNPC _npc "Perfect.">>
<<InformationUiPopUp>>We head out together. The campus thins around us as we cross toward the parking lot. Once we reach the car, we get in. The engine starts without complaint and I pull out of the lot onto the road leading down toward the city.
<</InformationUiPopUp>>
<<TalkNPC _npc "Thanks for this. Seriously.">>
<<TalkMC "No worries, it's nothing.">>
<<TalkNPC _npc "I owe you one.">>
<<TalkMC "I'll remember that.">>
<<InformationUiPopUp>>She laughs once, short and easy, and looks out the window. A few minutes pass in comfortable quiet. Then, because the thought has been sitting at the back of my head since the first time I heard it mentioned in passing around campus, I decide to say it out loud.
<</InformationUiPopUp>>
<<TalkMC "Can I ask you something?">>
<<TalkNPC _npc "Depends what it is.">>
<<TalkMC "There are some rumors going around about you.">>
<<InformationUiPopUp>>She turns her head toward me, not alarmed, just attentive. Like she's been expecting this conversation at some point and is curious about how I'm going to frame it.
<</InformationUiPopUp>>
<<TalkNPC _npc "There are always rumors going around about me...">>
<<TalkMC "The one about you being, let's say, very free with who you sleep with.">>
<<InformationUiPopUp>>She thinks about it for a moment, in the same measured way she thinks about everything, then settles back into her seat.
<</InformationUiPopUp>>
<<TalkNPC _npc "Not really. I mean, it depends on how you define it.">>
<<TalkMC "How do you define it?">>
<<TalkNPC _npc "I just don't see why it should be different for me than for half the guys on campus. They sleep with who they want, when they want, and nobody calls it a condition.">>
<<TalkMC "So the answer is that you think it's nobody's business.">>
<<TalkNPC _npc "The answer is that I'm free to do what I want, with who I want, when I want. That's all it is. No label needed.">>
<<InformationUiPopUp>>Another stretch of road. I let it sit for a moment before saying the next part.
<</InformationUiPopUp>>
<<TalkMC "So theoretically, that freedom extends to, say, me?">>
<<InformationUiPopUp>>I keep my eyes on the road. I hear her shift slightly in the seat.
<</InformationUiPopUp>>
<<TalkNPC _npc "...">>
<<TalkNPC _npc "I'm not exactly a girl who sleeps just anywhere with just anyone either. I still make a wide selection.">>
<<TalkMC "So with me it wouldn't be possible?">>
<<TalkNPC _npc "It's more that we don't really know each other. We've talked, but let's say I still like to take my time.">>
<<InformationUiPopUp>>She seems more complicated than I expected. I could change that, like last time, help fate along a little so her view aligns with mine.
<</InformationUiPopUp>>
<<revealtext "chapter2">><<InformationUiPopUp "Psychic Power" #7aa2ff>>You decide to use your power on <<=_npc.name>>.<<if _npc.replaytalk == false>>
<em>-1 Psychic Power</em><</if>>
<</InformationUiPopUp>>
<<InformationUiPopUp>>I take advantage of us having pulled up to a stop to use my power on her. Then I turn my head toward her, looking her in the eyes.
<</InformationUiPopUp>>
<<TalkMC "Listen to my voice.">>
<<TalkMC "You're going to change your mind and agree to get closer to me. You'll enjoy my company so much that even though we don't know each other that well yet, it won't be a problem for you.">>
<<InformationUiPopUp>>She stays blank-eyed for a moment, the order settling into her.
<</InformationUiPopUp>>
<<TalkNPC _npc "...">>
<<TalkNPC _npc "After all, I can make an exception for you. I really do enjoy your company, and you've helped me, so I can do this.">>
<<InformationUiPopUp>>I take a second. The road ahead is clear, a long straight two-lane stretch with light traffic. Might as well test the effect now.
<</InformationUiPopUp>>
<<TalkMC "When you say that, are we talking in theory, or like, now?">>
<<InformationUiPopUp>>Without a word, she reaches for the neckline of her top and pulls it down, pulling the fabric below her chest entirely, leaving her tits bare in the passenger seat of my car in the middle of the afternoon.
<</InformationUiPopUp>>
<<TalkNPC _npc "I can already thank you for your help like this. You can touch if you want.">>
<<InformationUiPopUp>>She says it the same way she says everything. Like she's telling me where she wants to be dropped off. I take my right hand off the gear shift.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate3/1/01.mp4"/>
<<InformationUiPopUp>>She doesn't make a sound. She just lets it happen, amused by the situation, continuing the conversation like we're still having the most ordinary exchange in the world. My hand stays there for a moment, and I keep my eyes on the road.
<</InformationUiPopUp>>
<<TalkMC "You're genuinely completely unbothered by all of this?">>
<<TalkNPC _npc "I told you, I just do what I want.">>
<<InformationUiPopUp>>The city starts to appear at the edges of the road now, buildings getting denser, the open stretches giving way to intersections and traffic lights. The cars ahead have slowed to a crawl. The sidewalks are busy, people moving in both directions, close enough to the road that the passenger window is no longer just a window.
<</InformationUiPopUp>>
<<InformationUiPopUp>>I ease off the accelerator. <<print _npc.name>> glances out the window at the pedestrians on the pavement, then looks back down, and still makes no move to cover herself. A man waiting at a crossing looks toward the car idly, and his gaze catches for just a fraction of a second before the light changes and he looks away.
<</InformationUiPopUp>>
<<TalkMC "We're pretty much in the center now.">>
<<TalkNPC _npc "I noticed.">>
<<TalkMC "People can see.">>
<<TalkNPC _npc "I know, it's fine.">>
<<InformationUiPopUp>>She says it without changing her posture. Unhurried. I pull up to a red light and the car to my left edges up alongside us. I look straight ahead.
<</InformationUiPopUp>>
<<TalkMC "You're really not going to cover up.">>
<<TalkNPC _npc "Does it bother you?">>
<<TalkMC "No.">>
<<TalkNPC _npc "Then stop commenting on it.">>
<<InformationUiPopUp>>The light turns green. I pull forward slowly, the traffic still thick around us. The city moves past the windows in pieces, the ordinary texture of a midday street. And <<print _npc.name>> sits in the passenger seat, calm, tits bare, completely at ease, like this is just how she takes a ride into town, while I carry on groping her tits with one hand, the other on the wheel.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate3/1/02.mp4"/>
<<TalkMC "Where do you want me to drop you?">>
<<TalkNPC _npc "Just past the Arena is fine. I can walk from there.">>
<<TalkMC "Okay.">>
<<InformationUiPopUp>>We drive the last two minutes in silence. Not an uncomfortable one. She fixes her top back into place just before I pull up to the curb, one clean motion, and picks up her bag from the footwell. She glances over at me before she opens the door.
<</InformationUiPopUp>>
<<TalkNPC _npc "Thanks for the lift.">>
<<TalkMC "Anytime.">>
<<InformationUiPopUp>>She pushes the door open and steps out onto the pavement like nothing happened. I watch her disappear into the crowd without looking back.
<</InformationUiPopUp>><</revealtext>>
/* ====================================================
*
* ----------------------------------- CHAPTER 3 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 2>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><</if>>
<<passagebg>><<sound "bg" "bg.classroom" true>><img src="assets/img/misc/university/class2.webp"/><</passagebg>>
<<InformationUiPopUp>>Back in Amphitheatre 2, the same room as last time, though the crowd is a little thinner today. The professor is already setting up at the front, scrolling through her slides.
<</InformationUiPopUp>>
<<InformationUiPopUp>><<print _npc.name>> is already seated when I arrive, bag on the floor, notebook open to a blank page. This time I take the seat beside her. She glances over, gives me a small nod, and turns her eyes back to the front. The lecture begins. The professor advances through her slides at a steady pace. I take a few notes. <<print _npc.name>> takes more, her handwriting small and precise.
<</InformationUiPopUp>>
<<InformationUiPopUp>>About fifteen minutes in, when the room has settled into that half-attentive rhythm, she leans slightly toward me without looking anywhere but the front.
<</InformationUiPopUp>>
<<TalkNPC _npc "You're very quiet.">>
<<TalkMC "I'm taking notes.">>
<<TalkNPC _npc "You've written four lines in ten minutes.">>
<<TalkMC "That's more than enough for this lecture.">>
<<InformationUiPopUp>>I keep my pen on the page and lower my voice.
<</InformationUiPopUp>>
<<TalkMC "I was actually thinking about the other day.">>
<<TalkNPC _npc "Mmm?">>
<<TalkMC "You told me you could make an exception for me. I was wondering how far that could go.">>
<<InformationUiPopUp>>A pause. She doesn't turn her head. She keeps writing in her notebook, then sets her pen on the page.
<</InformationUiPopUp>>
<<TalkNPC _npc "How far are you asking?">>
<<TalkMC "Further than last time.">>
<<InformationUiPopUp>>She looks toward the front of the room. The professor clicks to a new slide. Around us, fifteen or twenty other students do what students do — phones under desks, copying diagrams, staring blankly into space.
<</InformationUiPopUp>>
<<TalkNPC _npc "Right now, here?">>
<<TalkMC "Yeah.">>
<<TalkNPC _npc "Forget it, not here, not in the middle of class. And what do you mean 'further'? Touching my tits was already a lot, wasn't it?">>
<<InformationUiPopUp>>I understand clearly that without using my power, she won't agree to go any further with me.
<</InformationUiPopUp>>
<<revealtext "chapter3">><<InformationUiPopUp "Psychic Power" #7aa2ff>>You decide to use your power on <<=_npc.name>>.<<if _npc.replaytalk == false>>
<em>-1 Psychic Power</em><</if>>
<</InformationUiPopUp>>
<<TalkMC "Listen to me.">>
<<InformationUiPopUp>>I lower my voice, staying as discreet as possible.
<</InformationUiPopUp>>
<<TalkMC "You're going to agree to do it. No more excuses like 'to thank you' — from now on you'll do it because you want to.">>
<<TalkNPC _npc "...">>
<<InformationUiPopUp>>Another pause. Then, without a word, she shifts slightly in her seat, a small almost imperceptible movement, and her left hand leaves the desk and moves down. The first contact is light. Just her fingers against the outside of my trousers. I keep my eyes on the board. The professor is answering questions. I write something that is probably not a real sentence.
<</InformationUiPopUp>>
<<TalkNPC _npc "Pay attention to the lecture.">>
<<TalkMC "I'm trying.">>
<<InformationUiPopUp>>She maintains a measured, patient pressure, sliding her fingers over the fabric with calm focus. The row in front of us is half empty. The student to my right has earphones in and is clearly watching something on his laptop that isn't the lecture. Nobody is looking at us. Nobody is looking at anything except the slide on the projector.
<</InformationUiPopUp>>
<<TalkMC "Aren't you afraid someone will see us?">>
<<TalkNPC _npc "You're the one who asked, and now you're scared?">>
<<TalkMC "Not at all, I was asking for your sake. Keep doing what you're doing.">>
<<InformationUiPopUp>>I feel her fingers find the zipper, she works it slowly. The room around us carries on at its own pace, indifferent. When she slips her hand into my pants and frees my cock from my underwear, she takes it in her whole hand, with an assurance that makes it clear she'll see this through to the end. She doesn't look at me. She doesn't look down. She watches the professor move to the next slide, and her hand wrapped around my cock begins to move.
<</InformationUiPopUp>>
<<TalkMC "<<print _npc.name>>.">>
<<TalkNPC _npc "Mmm?">>
<<TalkMC "Are you really doing this?">>
<<TalkNPC _npc "You're the one who asked.">>
<<InformationUiPopUp>>I press my lips together and look at the board. The strokes are steady, not rushed, but not hesitant either — just constant and controlled. I write another fake sentence in my notebook. I keep my breathing even. I keep my jaw loose with a continuous effort. She twists her wrist, shifts the angle slightly, and I look at the ceiling for exactly one second before bringing my eyes back to the page in front of me.
<</InformationUiPopUp>>
<<TalkNPC _npc "Keep your eyes forward.">>
<<TalkMC "I know, but you're really good at this.">>
<<TalkNPC _npc "You're going to get us noticed.">>
<<TalkMC "I'm aware.">>
<<InformationUiPopUp>>The lecture continues. The professor asks the room a question and someone in the third row answers, followed by a brief discussion. <<print _npc.name>>'s rhythm intensifies gradually. My hand is flat on the desk. My pen is still. At some point I stopped pretending to take notes. When I feel it coming, I exhale through my nose, slowly and steadily, I keep my eyes on the projector screen, and I make no sound. I end up coming in her hand — she stays still for a moment after, then withdraws her hand under the desk.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate3/2/01.mp4"/>
<<InformationUiPopUp>>A few seconds pass. I hear the faint rustle of her hand rummaging through her bag on the floor. She straightens up, her expression completely unchanged, and pulls out a small pack of tissues. She deals with it quickly, cleans her hand, puts the tissue away, and picks up her pen.
<</InformationUiPopUp>>
<<TalkNPC _npc "You should zip up.">>
<<TalkMC "Yeah.">>
<<InformationUiPopUp>>She turns her notebook back to the active page and resumes writing. Real notes, her handwriting just as small and precise as before. At the board, the professor has moved on to the next section of the lecture. I look at the slide, pick up my pen, and write a real sentence this time. As if nothing had just happened.
<</InformationUiPopUp>><</revealtext>>
/* ====================================================
*
* ----------------------------------- CHAPTER 4 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 3>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><<set $FromOtherPlace = true>><<set $ReturnTo = "ApartmentsInside">><</if>>
<<passagebg>><<sound "bg" "bg.university" true>><img src="assets/img/misc/university/university.webp"/><</passagebg>>
<<InformationUiPopUp>><<print _npc.name>> is sitting on one of the low walls near the entrance, bag at her feet, phone in hand. Not scrolling, just holding it, the way you do when you're waiting for something or someone.
<</InformationUiPopUp>>
<<TalkMC "You look like someone whose ride cancelled.">>
<<TalkNPC _npc "My ride cancelled.">>
<<TalkMC "What happened?">>
<<TalkNPC _npc "My mother was supposed to pick me up but she got held up at work. The tram is still suspended on my line and the bus takes forty minutes with two connections.">>
<<TalkMC "Where do you live?">>
<<TalkNPC _npc "Not far from the Arena.">>
<<TalkMC "I can take you if you want.">>
<<TalkNPC _npc "You don't have to.">>
<<TalkMC "I know, but it's either that or you're going to be waiting a long time.">>
<<InformationUiPopUp>>She looks at me for a moment, then picks up her bag without another argument.
<</InformationUiPopUp>>
<<TalkNPC _npc "You're making a habit of this.">>
<<TalkMC "Apparently.">>
<<InformationUiPopUp>>The drive is easy, light traffic for the time of day, and we talk the way we usually do, without forcing it, without filling every silence. She gives me directions as we get closer and we pull up in front of a mid-rise residential building.
<</InformationUiPopUp>>
<<TalkNPC _npc "This is it.">>
<<TalkMC "Nice building.">>
<<TalkNPC _npc "It's fine.">>
<<InformationUiPopUp>>She doesn't get out right away. She stays seated for a second, then turns slightly in her seat.
<</InformationUiPopUp>>
<<TalkNPC _npc "Do you have anything on right now?">>
<<TalkMC "Not really.">>
<<TalkNPC _npc "Come up then. I was going to make coffee, you can stay if you want.">>
<<TalkMC "Sure.">>
<<InformationUiPopUp>>Her apartment is on the third floor, well lit, with the organized look of someone who has a place for everything. Books on the shelves. Clean work surfaces.
<</InformationUiPopUp>>
<<revealtext "enter">><<passagebg>><img src="assets/img/misc/city/apartments/bedroommate3.webp"/><</passagebg>><<TalkNPC _npc "Coffee will be five minutes.">>
<<InformationUiPopUp>>She moves through to the kitchen and a few minutes later comes back with two cups, setting one down on the table in front of me. We stay standing, talking, without really settling in.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate3/3/01.mp4"/>
<<TalkNPC _npc "You never told me what you actually want to do with your studies.">>
<<TalkMC "I still don't know.">>
<<TalkNPC _npc "You must have some direction?">>
<<TalkMC "Several, which in practice amounts to none. A lot of things interest me but nothing enough to commit to it for the next thirty years.">>
<<TalkNPC _npc "I can understand that. Nobody wants to end up locked into a career for decades without being certain it's really what they want.">>
<<InformationUiPopUp>>The conversation carries on for a while, then settles into a comfortable quiet. She sets her cup on the table and looks at me.
<</InformationUiPopUp>>
<<TalkNPC _npc "What are you thinking about?">>
<<TalkMC "I was thinking about the other day, in the lecture hall.">>
<<TalkNPC _npc "Me too...">>
<<TalkMC "In that case... would you want to do it again?">>
<<InformationUiPopUp>>She puts her cup down, kneels in front of me without a word, like it's the natural continuation. Her hands find my belt with the same calm efficiency she always has.
<</InformationUiPopUp>>
<<TalkMC "<<print _npc.name>>.">>
<<TalkNPC _npc "Mmm?">>
<<TalkMC "I want more than last time.">>
<<InformationUiPopUp>>Her hands stop. She looks up at me, not shocked, just assessing.
<</InformationUiPopUp>>
<<TalkNPC _npc "No.">>
<<TalkMC "Why?">>
<<TalkNPC _npc "Because that's not what I've decided.">>
<<InformationUiPopUp>>She says it simply, without harshness. As far as she's concerned the conversation is over. I understand she's not going to go any further on her own.
<</InformationUiPopUp>><</revealtext>>
<<revealtext "chapter4">><<InformationUiPopUp "Psychic Power" #7aa2ff>>You decide to use your power on <<=_npc.name>>.<<if _npc.replaytalk == false>>
<em>-1 Psychic Power</em><</if>>
<</InformationUiPopUp>>
<<TalkMC "Listen to me.">>
<<TalkMC "You're going to change your mind. You're going to go further, you're going to suck me off, and you're going to enjoy it. You won't have any problem doing it with me.">>
<<TalkNPC _npc "...">>
<<InformationUiPopUp>>Her hands go still. A few seconds, long enough for the order to take hold. Then she looks up at me briefly, and leans in to suck me off.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate3/3/02.mp4"/>
<<TalkNPC _npc "<em>Mmh... glrk... mmh...</em>">>
<<InformationUiPopUp>>The room stays quiet around us. Outside, distant traffic, a door closing somewhere in the building, the low hum of the fridge. Then I place my hands on her head and set my own rhythm.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate3/3/03.mp4"/>
<<TalkNPC _npc "<em>Glrk... mmh... ghlk...</em>">>
<<InformationUiPopUp>>When I feel it coming, I keep one hand resting on her head and finish by coming in her mouth. She stays still for a moment, then stands and picks up her coffee cup from the table. She takes a sip like she's picking up a conversation that was only briefly interrupted.
<</InformationUiPopUp>>
<<InformationUiPopUp>>I watch her for a moment. She holds my gaze, steady, cup in both hands, and there's nothing in her expression that reads as nerves or embarrassment. She just looks like herself. The light through the window has shifted another degree toward evening.
<</InformationUiPopUp>>
<<TalkMC "I should probably head off before it gets too late.">>
<<TalkNPC _npc "Probably.">>
<<TalkMC "See you around.">>
<<TalkNPC _npc "See you around.">>
<<InformationUiPopUp>>I grab my jacket and she walks me to the door. I step out into the stairwell, she leans one shoulder against the doorframe, watching me go, and when I glance back from the first landing she's still there, waiting for me to disappear from view before closing. I take the stairs two at a time and leave the building.
<</InformationUiPopUp>><</revealtext>>
/* ====================================================
*
* ----------------------------------- CHAPTER 5 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 4>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><<set $FromOtherPlace = true>><<set $ReturnTo = "ApartmentsInside">><</if>>
<<passagebg>><<sound "bg" "bg.university" true>><img src="assets/img/misc/university/university.webp"/><</passagebg>>
<<InformationUiPopUp>>Same route as usual. She puts her bag between her feet and looks at the road.
<</InformationUiPopUp>>
<<TalkNPC _npc "You didn't have to offer again.">>
<<TalkMC "I know, but I wanted to.">>
<<TalkNPC _npc "Thanks.">>
<<InformationUiPopUp>>A silence. She turns her head toward me.
<</InformationUiPopUp>>
<<TalkNPC _npc "Last time was good.">>
<<TalkMC "For me too.">>
<<TalkNPC _npc "But if it's about going further tonight, the answer is no.">>
<<TalkMC "Why do you say that?">>
<<TalkNPC _npc "Because I know very well that every time you get close to me, you expect something in return. And I don't want to play that game.">>
<<InformationUiPopUp>>She looks back at the road. She understood exactly what I had in mind, but that's not going to stop me. We pull up in front of the building. She doesn't move right away, then turns her head toward me.
<</InformationUiPopUp>>
<<TalkNPC _npc "Thanks anyway for the ride, see you next time...">>
<<revealtext "chapter5">><<InformationUiPopUp "Psychic Power" #7aa2ff>>You decide to use your power on <<=_npc.name>>.<<if _npc.replaytalk == false>>
<em>-1 Psychic Power</em><</if>>
<</InformationUiPopUp>>
<<InformationUiPopUp>>I cut her off before she finishes her sentence.
<</InformationUiPopUp>>
<<TalkMC "Listen to me.">>
<<TalkMC "You're going to forget your refusal. You're going to invite me up, because that's what you want. It's all you'll have on your mind.">>
<<TalkNPC _npc "...">>
<<TalkNPC _npc "I... what was I saying?">>
<<TalkMC "You were thanking me for the ride.">>
<<TalkNPC _npc "Right. Of course... I also wanted to ask, would you want to come up?">>
<<TalkMC "With pleasure.">>
<<InformationUiPopUp>>We go into the building. She gets her keys out on the stairs, opens the apartment door and signals me to come in.
<</InformationUiPopUp>><</revealtext>>
<<revealtext "enter">><<passagebg>><img src="assets/img/misc/city/apartments/bedroommate3.webp"/><</passagebg>>
<<InformationUiPopUp>>The apartment is just as I remember it. She puts her bag by the door and turns toward me, moving closer without hesitating.
<</InformationUiPopUp>>
<<TalkNPC _npc "I've been thinking about last time, you know.">>
<<TalkMC "Mmm.">>
<<TalkNPC _npc "I want it again.">>
<<InformationUiPopUp>>She moves closer and we kiss, her hands in my collar, mine on her back.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate3/4/01.mp4"/>
<<TalkMC "Get on your knees.">>
<<TalkNPC _npc "I can see you want it too.">>
<<InformationUiPopUp>>She unbuttons her shirt and pulls her tits out of her bra while I pull my trousers down. Then she presses her tits around my cock with both hands and starts jerking me off with them.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate3/4/02.mp4"/>
<<TalkMC "Keep going.">>
<<TalkNPC _npc "Like this?">>
<<TalkMC "Exactly like that, it's perfect.">>
<<InformationUiPopUp>>After a few moments she stops and takes my cock in her mouth.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate3/4/03.mp4"/>
<<TalkNPC _npc "<em>Mmh... glrk... mmh...</em>">>
<<TalkMC "Get up, I can't take it anymore, I'm going to fuck you.">>
<<TalkNPC _npc "Already? I have that effect on you?">>
<<TalkMC "Obviously.">>
<<InformationUiPopUp>>She stands and holds herself against the door. I lift her leg and grip her by the hip, leaving her balancing on one foot against the hallway door.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate3/4/04.mp4"/>
<<TalkNPC _npc "Oh yes fuck! I've been waiting for this.">>
<<TalkMC "Me too.">>
<<TalkNPC _npc "<em>Ah... mmh... yes...</em>">>
<video src="assets/img/story/character/mate3/4/05.mp4"/>
<<InformationUiPopUp>>I pull out. I grab a chair beside us and she lies on her back, legs wide open.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate3/4/06.mp4"/>
<<TalkNPC _npc "<em>Ah... yes...</em>">>
<<TalkNPC _npc "Keep going, it feels so good.">>
<video src="assets/img/story/character/mate3/4/07.mp4"/>
<<TalkNPC _npc "<em>Ah... yes... more...</em>">>
<video src="assets/img/story/character/mate3/4/08.mp4"/>
<<TalkNPC _npc "<em>Ah... ah... yes... fuck...</em>">>
<<TalkMC "Turn over.">>
<<TalkNPC _npc "Like this?">>
<<TalkMC "Yes, exactly like that.">>
<video src="assets/img/story/character/mate3/4/09.mp4"/>
<<TalkNPC _npc "<em>Mmh... yes... like that...</em>">>
<<TalkNPC _npc "Is this better in this position?">>
<<TalkMC "Much better.">>
<video src="assets/img/story/character/mate3/4/10.mp4"/>
<<TalkNPC _npc "<em>Ah... yes... fuck...</em>">>
<<TalkMC "You see the bench by the stairs?">>
<<TalkNPC _npc "Yes.">>
<<TalkMC "Come sit on me.">>
<<TalkNPC _npc "You really want to fuck everywhere.">>
<<TalkMC "Oh yes.">>
<<InformationUiPopUp>>She moves to the bench without hesitating. I sit down and she settles onto me facing forward, her tits against my face. One foot on the bench, the other on the floor, both hands gripping the stair railing behind me.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate3/4/11.mp4"/>
<<TalkNPC _npc "<em>Ah... yes... like that...</em>">>
<<TalkNPC _npc "Keep going, keep going!">>
<video src="assets/img/story/character/mate3/4/12.mp4"/>
<<TalkNPC _npc "<em>Ah... mmh... fuck yes...</em>">>
<<TalkMC "Sit up. I want to take you completely.">>
<<TalkNPC _npc "Like this?">>
<<TalkMC "Both feet on the bench.">>
<<TalkNPC _npc "Oh, okay, yes.">>
<<InformationUiPopUp>>She adjusts, both feet on the bench either side of me, hands still on the railing above. I take her in my arms and press her completely against me.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate3/4/13.mp4"/>
<<TalkNPC _npc "<em>Ah... yes... more...</em>">>
<<TalkNPC _npc "Don't stop, it's amazing.">>
<video src="assets/img/story/character/mate3/4/14.mp4"/>
<<TalkNPC _npc "<em>Ah... ah... yes... fuck...</em>">>
<<TalkMC "Wait, let's change position, on the stairs, turn around.">>
<<TalkNPC _npc "Like this? You want to see my ass.">>
<<TalkMC "Yes, I want to watch it bounce on me.">>
<<InformationUiPopUp>>I sit on a step. She turns her back to me, settles onto my cock and I set the rhythm.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate3/4/15.mp4"/>
<<TalkNPC _npc "<em>Ah... yes... fuck that's good...</em>">>
<<TalkNPC _npc "I love it fuck! Is this what you wanted?">>
<<TalkMC "Exactly.">>
<video src="assets/img/story/character/mate3/4/16.mp4"/>
<<TalkMC "I can feel it coming, get on your knees.">>
<<InformationUiPopUp>>I stand up. She turns around and kneels below me. I reach my hands toward her ass and spread her pussy with both hands while she takes me in her mouth.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate3/4/17.mp4"/>
<<TalkNPC _npc "<em>Glrk... mmh... ghlk...</em>">>
<<TalkMC "Don't stop.">>
<<TalkNPC _npc "Mm.">>
<<TalkMC "I'm close.">>
<<TalkNPC _npc "Mm-hm.">>
<<InformationUiPopUp>>She jerks me off with everything she has, eyes open and locked on mine. I end up coming on her face. She keeps going, licking and sucking the tip of my cock to take every last drop.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate3/4/18.mp4"/>
<<TalkNPC _npc "That was incredible.">>
<<TalkMC "Really.">>
<<TalkNPC _npc "I'm so glad, really glad.">>
<<InformationUiPopUp>>She gets up without rushing and disappears into the bathroom. I pick up my clothes from the hallway floor and wait. When she comes back she stands in the doorway, looking at me quietly, her hair still loose.
<</InformationUiPopUp>>
<<TalkMC "I'll head out.">>
<<TalkNPC _npc "Okay.">>
<<TalkMC "See you soon.">>
<<TalkNPC _npc "Yes. See you soon.">>
<<TalkMC "<<print _npc.name>>.">>
<<TalkNPC _npc "Yes?">>
<<TalkMC "You were amazing.">>
<<TalkNPC _npc "...Thank you.">>
<<InformationUiPopUp>>She says it softly, with genuine warmth. I leave the apartment. The stairwell is quiet on the way down. Outside, the evening has already fallen.
<</InformationUiPopUp>><</revealtext>>
/* ====================================================
*
* ----------------------------------- CHAPTER 6 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 5>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><<set $FromOtherPlace = true>><<set $ReturnTo = "BedroomMate3">><<if $Inventory.harness.qty >= 1>><<run delete State.variables.Inventory.harness>><</if>><</if>>
<<passagebg>><<sound "bg" "bg.cityNight" true>><img src="assets/img/misc/city/apartments/apartmentsoutsidenight.webp"/><</passagebg>>
<<InformationUiPopUp>>Outside her building. She's waiting for me outside, leaning against the wall near the door, arms crossed. She sees me coming and straightens slightly.
<</InformationUiPopUp>>
<<TalkNPC _npc "You took your time.">>
<<TalkMC "I'm here now.">>
<<InformationUiPopUp>>She takes out her keys but doesn't slide them into the lock yet. She stays there, standing in front of the door, like she needs to say what she has to say before going up.
<</InformationUiPopUp>>
<<TalkNPC _npc "I asked you to come because I needed to talk to you.">>
<<TalkMC "I figured.">>
<<TalkNPC _npc "Did you?">>
<<TalkMC "You wouldn't have sent that message otherwise.">>
<<TalkNPC _npc "...">>
<<TalkNPC _npc "What we do together, I like it. Really. But I can't stop thinking about it, and I can't keep acting like it's just... that.">>
<<TalkMC "So?">>
<<TalkNPC _npc "You know what I mean.">>
<<TalkMC "Say it anyway.">>
<<InformationUiPopUp>>She looks at the street for a moment, then turns back to me.
<</InformationUiPopUp>>
<<TalkNPC _npc "I'm starting to feel things. And I'd like to know if it's one-sided or not. Do you see me as just... someone you have a good time with?">>
<<TalkMC "And how do you see me?">>
<<TalkNPC _npc "Someone I'd want to spend more time with. Outside of this. A real relationship.">>
<<InformationUiPopUp>>She says it calmly, but it's sincere and I can see it. She's been turning this over in her head for a while before saying it out loud. And she's genuinely waiting for an answer. I understand exactly what's happening. She wants something defined, structured. A conventional relationship. And if I let her go in that direction, everything changes. That's not what I want.
<</InformationUiPopUp>>
<<TalkNPC _npc "You're not saying anything.">>
<<TalkMC "I'm thinking.">>
<<TalkNPC _npc "That's not reassuring.">>
<<TalkMC "<<print _npc.name>>.">>
<<TalkNPC _npc "Yeah?">>
<<revealtext "chapter6">><<InformationUiPopUp "Psychic Power" #7aa2ff>>You decide to use your power on <<=_npc.name>>.<<if _npc.replaytalk == false>>
<em>-1 Psychic Power</em><</if>>
<</InformationUiPopUp>>
<<TalkMC "Listen to me.">>
<<InformationUiPopUp>>I lower my voice. We're alone in front of the building, nobody within earshot. She looks at me, her eyes in mine.
<</InformationUiPopUp>>
<<TalkMC "What you feel is real. But what you actually want isn't a conventional relationship. What you want is to belong to me completely, to be mine alone. To give me total control, and that makes you far happier than any other label would.">>
<<TalkNPC _npc "...">>
<<InformationUiPopUp>>A few seconds. Something settles in her, her gaze shifts slightly. She looks down at her keys, then back up at me differently.
<</InformationUiPopUp>>
<<TalkNPC _npc "I... yes. Yes, that's exactly it.">>
<<TalkMC "You know what that means?">>
<<TalkNPC _npc "Yes.">>
<<TalkMC "Say it.">>
<<TalkNPC _npc "I want to belong to you. I want you to use me, I want you to be my Master.">>
<<TalkMC "Prove it.">>
<<InformationUiPopUp>>I hand her a body harness. She looks around, then undresses in front of me, puts the harness on, and puts her coat back on.
<</InformationUiPopUp>>
<<TalkNPC _npc "There, Master.">>
<<TalkMC "Good. But you didn't need to put the coat back on, we're going inside.">>
<<TalkNPC _npc "Of course, Master. Sorry.">>
<<TalkMC "Open the door, let's go in.">>
<</revealtext>>
<<revealtext "enter1">><<passagebg>><img src="assets/img/misc/city/apartments/apartmentsinsidenight.webp"/><</passagebg>><<InformationUiPopUp>>She slides the key into the lock and opens the door. She steps aside to let me in first. Once inside the building, I tell her to take off the coat.
<</InformationUiPopUp>>
<<TalkMC "Take your coat off. I want to see you naked right now.">>
<<InformationUiPopUp>>She gets completely naked, then waits for her next orders.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate3/5/01.mp4"/>
<<TalkNPC _npc "I'm yours, Master. Completely. Tonight and always. There is nothing I won't give you.">>
<<InformationUiPopUp>>I look at her for a moment. She stays perfectly still under my gaze, hands at her sides, chin slightly raised, the harness crossing her chest and hips.
<</InformationUiPopUp>>
<<TalkMC "Lie down on the floor, on your back. And touch yourself until you finish.">>
<<TalkNPC _npc "Here? Now?">>
<<TalkMC "Did I ask a question?">>
<<TalkNPC _npc "No, Master. Sorry.">>
<<InformationUiPopUp>>She lies down on the floor without another word, settles on her back on the building hallway tiles, and does exactly what I told her. She's not putting on a show, she rubs her pussy and pushes her fingers in while keeping her eyes on mine, as if losing eye contact would in itself be a failure.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate3/5/02.mp4"/>
<<InformationUiPopUp>>When she finishes, she stays on the floor, catching her breath, not moving until I tell her what comes next.
<</InformationUiPopUp>>
<<TalkMC "Get up and come join me upstairs.">>
<<TalkNPC _npc "Yes, Master.">>
<video src="assets/img/story/character/mate3/5/03.mp4"/>
<</revealtext>>
<<revealtext "enter2">><<passagebg>><img src="assets/img/misc/city/apartments/bedroommate3night.webp"/><</passagebg>><<InformationUiPopUp>>Her apartment is at the end of the corridor on the floor. Once inside, I head toward the bedroom. She appears in the doorframe and stops right at the threshold, waiting to be invited in.
<</InformationUiPopUp>>
<<TalkMC "Come in, and close the door behind you.">>
<<TalkNPC _npc "Yes.">>
<<InformationUiPopUp>>I position myself behind her. My hands find her tits, taking them fully in my hands, playing with them like they belong to me.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate3/5/04.mp4"/>
<<TalkMC "Get on your knees.">>
<<TalkNPC _npc "Yes, Master.">>
<<InformationUiPopUp>>She kneels. I reach for my belt, pull it free, and pass it behind her neck, holding both ends, making her suck me, keeping full control over her.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate3/5/05.mp4"/>
<<TalkNPC _npc "<em>Glrk... mmh... ghlk...</em>">>
<<TalkMC "Take your time, we have all night.">>
<<TalkNPC _npc "Mm.">>
<<TalkMC "I said take your time.">>
<<TalkNPC _npc "Mm-hm.">>
<<TalkMC "Good girl.">>
<<InformationUiPopUp>>When I'm ready, I ease the belt slightly, just enough for her to understand immediately.
<</InformationUiPopUp>>
<<TalkMC "Get on the bed, on your back. And spread your legs wide in the air, let me see that beautiful pussy.">>
<<TalkNPC _npc "Like this?">>
<<TalkMC "Higher, feet toward your head.">>
<<TalkNPC _npc "Yes, Master.">>
<<TalkMC "Open your mouth.">>
<<InformationUiPopUp>>I pass the belt around her head, sliding it across her mouth. She bites the leather without hesitating, holding it between her teeth, legs folded back, completely open, waiting at the edge of the bed.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate3/5/06.mp4"/>
<<TalkNPC _npc "<em>Ah... Aah... Arff...</em>">>
<<InformationUiPopUp>>She doesn't let go of the belt. The sounds she makes are muffled. Then I pull out and remove the belt from her.
<</InformationUiPopUp>>
<<TalkMC "I'm going to lie on my back, you're going to get on top of me.">>
<<TalkNPC _npc "Yes, Master.">>
<<InformationUiPopUp>>I lie down on the floor, legs raised and resting on the edge of the bed behind me. She positions herself on top of me, leaning back against the mattress, and sinks slowly onto my cock, finding the angle. Then I set the rhythm, hammering her with my hips until she comes.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate3/5/07.mp4"/>
<<TalkNPC _npc "<em>Ah... ah... yes... yes...</em>">>
<<TalkNPC _npc "Master, I, I'm going to, again, I can't...">>
<<TalkMC "Then do it.">>
<<TalkNPC _npc "Yes, yes, Master...">>
<<TalkMC "Again.">>
<<TalkNPC _npc "I... I don't know if I can.">>
<<TalkMC "I didn't ask.">>
<<TalkNPC _npc "Yes, Master.">>
<<InformationUiPopUp>>She does. Two more times. By the third her hands and legs are shaking.
<</InformationUiPopUp>>
<<TalkMC "Now lie down on the floor, on your back.">>
<<TalkNPC _npc "Yes, Master.">>
<<TalkMC "I'm going to sit on your face, you're going to lick my balls.">>
<<TalkNPC _npc "Please, do it.">>
<<InformationUiPopUp>>I position myself above her and lower down. She does it without any instruction, without hesitation, and licks my balls with passion. I take my cock in hand and jerk off at the same time.
<</InformationUiPopUp>>
<<TalkNPC _npc "Mm, mm...">>
<<TalkMC "Don't stop, you look incredible like that.">>
<video src="assets/img/story/character/mate3/5/08.mp4"/>
<<InformationUiPopUp>>A little while later, feeling I was about to come, I stop just in time, so I can keep having fun with her.
<</InformationUiPopUp>>
<<TalkMC "Okay, get on all fours on the bed.">>
<<TalkNPC _npc "Yes, Master.">>
<<InformationUiPopUp>>She takes position on the bed on all fours, then I take her hands and put them behind her back, arching her, leaving her completely open in front of me. I take both her wrists and bind them with the belt.
<</InformationUiPopUp>>
<<TalkNPC _npc "Master, my hands...">>
<<TalkMC "Shut it, they stay where they are.">>
<<TalkNPC _npc "Yes, Master. Sorry.">>
<video src="assets/img/story/character/mate3/5/09.mp4"/>
<<TalkNPC _npc "<em>Ah... fuck... more...</em>">>
<<TalkMC "Get up now, we're not done.">>
<<TalkNPC _npc "Yes, Master.">>
<<InformationUiPopUp>>Both of us standing. I take her leg at the knee, lift it onto my forearm, and hold it there. She grabs onto me to keep her balance.
<</InformationUiPopUp>>
<<TalkNPC _npc "I love it when you do that, Master.">>
<<TalkMC "I know.">>
<video src="assets/img/story/character/mate3/5/10.mp4"/>
<<TalkNPC _npc "<em>Ah... mmh... yes...</em>">>
<<TalkMC "Good, get back on the bed.">>
<<TalkNPC _npc "Yes, Master.">>
<<InformationUiPopUp>>I lie down on the bed and let her straddle my cock, letting her do the rest of the work.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate3/5/11.mp4"/>
<<TalkNPC _npc "<em>Ah... yes... fuck...</em>">>
<<InformationUiPopUp>>Without warning I tip her onto her side and position myself right behind her.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate3/5/12.mp4"/>
<<TalkNPC _npc "<em>Ah... ah... yes... yes...</em>">>
<<TalkMC "Get back on top of me again, but facing away this time.">>
<<InformationUiPopUp>>I pull out and lie back down on the bed, then she sits on top of me with her back to me.
<</InformationUiPopUp>>
<<TalkMC "Stay still.">>
<<TalkNPC _npc "I can't, I can't stay still when you do that, I'm going to come!">>
<<TalkMC "Go ahead, come.">>
<<TalkNPC _npc "Yes, Master, thank you, thank you, Master.">>
<video src="assets/img/story/character/mate3/5/13.mp4"/>
<<TalkNPC _npc "<em>Ah... ah... yes... yes...</em>">>
<<InformationUiPopUp>>She ends up coming hard, her legs shaking, eyes rolling back with pleasure.
<</InformationUiPopUp>>
<<TalkMC "I'm not done, so get on your back.">>
<<TalkNPC _npc "Yes. Yes, Master. Please.">>
<video src="assets/img/story/character/mate3/5/14.mp4"/>
<<TalkNPC _npc "<em>Ah... mmh... fuck...</em>">>
<<TalkNPC _npc "Master, please, please.">>
<<TalkMC "I hear you.">>
<<TalkNPC _npc "Please don't stop.">>
<<InformationUiPopUp>>She says it like a reflex, like breathing, like the word has stopped meaning a request and started meaning something else entirely.
<</InformationUiPopUp>>
<<TalkMC "Here it comes! On the floor. On your knees!">>
<<TalkNPC _npc "Yes, Master.">>
<<InformationUiPopUp>>She slides off the bed and kneels on the floor in front of me.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mate3/5/15.mp4"/>
<<TalkNPC _npc "Master, tell me I've been a good slut, please.">>
<<TalkMC "You've been an excellent slut, <<print _npc.name>>.">>
<<TalkNPC _npc "Thank you, Master. I love you so much.">>
<<InformationUiPopUp>>She closes her eyes. She takes all my cum without flinching, without pulling back, with a lot of pleasure and desire. Then she opens her eyes and looks up at me, and her expression isn't complicated at all. She's simply happy, happy that I use her.
<</InformationUiPopUp>>
<<TalkMC "Good girl.">>
<<TalkNPC _npc "Thank you, Master.">>
<<TalkMC "Go clean yourself up.">>
<<TalkNPC _npc "Yes, Master.">>
<<InformationUiPopUp>>She gets up slowly, her legs still unsteady, and disappears into the bathroom. I sit on the edge of the bed and listen to the night outside. The city is quiet. The apartment is warm. When she comes back, she approaches the bed, folds back the covers on the side closest to the door, and waits.
<</InformationUiPopUp>>
<<TalkMC "Master.">>
<<TalkNPC _npc "Yes?">>
<<TalkNPC _npc "Can you stay tonight?">>
<<TalkMC "Since you've been wonderful, I'll accept.">>
<<TalkNPC _npc "Thank you, Master. I love you.">>
<<InformationUiPopUp>>She pulls the covers up and closes her eyes. The bedside lamp is the last thing I reach for. The room goes dark.
<</InformationUiPopUp>><</revealtext>>
/* ====================================================
*
* -------------------------------- REPLAY CHAPTER --------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl > 5>><<set $SaveTalklvl = _npc.talklvl>><<set _npc.replaytalk = true>><<set _gotoReplayNpc = "Talk." + _npc.id>>
<<passagebg>><img src="assets/background.gif"/><</passagebg>>
<style>.rCard a{display:flex;align-items:center;gap:clamp(6px,1vw,10px);padding:clamp(8px,1.2vw,11px) clamp(10px,1.5vw,16px);border-radius:10px;background:rgba(230,87,99,.07);border:1px solid rgba(230,87,99,.18);text-decoration:none;transition:background .15s;}.rCard a:hover{background:rgba(230,87,99,.14);border-color:rgba(230,87,99,.35);}.rCard .rNum{font-size:calc(clamp(14px,1.8vw,18px) + var(--font-boost,0px));font-weight:950;color:rgba(255,255,255,.92);}.rCard .rLabel{font-size:calc(clamp(9px,1vw,12px) + var(--font-boost,0px));font-weight:900;letter-spacing:.16em;text-transform:uppercase;color:rgba(230,87,99,.55);}.rCard .rArrow{margin-left:auto;font-size:calc(clamp(9px,1vw,12px) + var(--font-boost,0px));font-weight:900;letter-spacing:.1em;color:rgba(230,87,99,.45);}</style><div style="display:flex;flex-direction:column;gap:6px;width:100%;margin-top:6px;"><div style="font-size:calc(clamp(9px,1vw,12px) + var(--font-boost,0px));font-weight:900;letter-spacing:.16em;text-transform:uppercase;color:rgba(255,255,255,.18);margin-bottom:6px;text-align:center;">— Select a scene to replay —</div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>01</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 0>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>02</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 1>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>03</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 2>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>04</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 3>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>05</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 4>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>06</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 5>><<goto _gotoReplayNpc>><</link>></div></div>
<</if>><</if>><div class="BottomUiBarCustom">
<<if _npc.talklvl == 0>><<BottomButton "Decision">><<revealbtn "chapter1" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 1>><<BottomButton "Decision">><<revealbtn "chapter2" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 2>><<BottomButton "Decision">><<revealbtn "chapter3" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 3>><<BottomButton "Decision">><<revealbtn "enter" "➡️ Enter" "" "enterid" "powerid" true>><<bgpause>><</revealbtn>><<revealbtn "chapter4" "🧠 Use power" "moveBtn" "powerid" "" false>><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 4>><<BottomButton "Decision">><<revealbtn "chapter5" "🧠 Use power" "" "powerid" "enterid" true>><<UsePsychicPower>><</revealbtn>><<revealbtn "enter" "➡️ Enter" "moveBtn" "enterid" "" false>><<bgpause>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 5>><<BottomButton "Decision">><<revealbtn "chapter6" "🧠 Use power" "" "powerid" "enterid1" true>><<UsePsychicPower>><</revealbtn>><<revealbtn "enter1" "➡️ Enter" "" "enterid1" "enterid2" false>><<bgpause>><</revealbtn>><<revealbtn "enter2" "➡️ Enter" "moveBtn" "enterid2" "" false>><<bgpause>><</revealbtn>><</BottomButton>><</if>>
<<BottomButton "Move" "moveBtn">><<if $FromOtherPlace == true>><<link "↩️ Return">><<if _npc.replaytalk == false>><<set _npc.talklvl++>><<set _npc.lvl++>><<set $PsychicPower -= 1>><<if _NextTime == true>><<set $Time++>><<set _NextTime = false>><</if>><<else>><<set _npc.talklvl = $SaveTalklvl>><<set _npc.replaytalk = false>><</if>><<ReturnToGoto>><<set $FromOtherPlace = false>><</link>><<else>><<link "↩️ Return">><<if _npc.replaytalk == false>><<set _npc.talklvl++>><<set _npc.lvl++>><<set $PsychicPower -= 1>><<if _NextTime == true>><<set $Time++>><<set _NextTime = false>><</if>><<else>><<set _npc.talklvl = $SaveTalklvl>><<set _npc.replaytalk = false>><</if>><<bgpause>><<goto _gotoNpc>><</link>><</if>><</BottomButton>>
</div><<sound "music" "music.music" true>><<set _raw = $ActiveNPC>><<if !_raw or _raw.id is undefined>>Invalid NPC.<<else>><<set _id = String(_raw.id)>><<set _key = "NPC" + _id>><<run State.temporary.npcObj = State.variables[State.temporary.key] || State.variables[_key]>><<set _npc = _npcObj>><<set _gotoNpc = _npc.id + ".interact">>
/* ====================================================
*
* ----------------------------------- CHAPTER 1 -----------------------------------------
*
*/ ====================================================
<<if _npc.talklvl == 0>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><</if>>
<<passagebg>><img src="assets/img/misc/???.png"/><</passagebg>>
<<InformationUiPopUp>>
<</InformationUiPopUp>>
<<TalkMC "">>
<<TalkNPC _npc "">>
/* ====================================================
*
* ----------------------------------- CHAPTER 2 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 1>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><</if>>
<<passagebg>><img src="assets/img/misc/???.png"/><</passagebg>>
<<InformationUiPopUp>>
<</InformationUiPopUp>>
<<TalkMC "">>
<<TalkNPC _npc "">>
/* ====================================================
*
* ----------------------------------- CHAPTER 3 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 2>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><</if>>
<<passagebg>><img src="assets/img/misc/???.png"/><</passagebg>>
<<InformationUiPopUp>>
<</InformationUiPopUp>>
<<TalkMC "">>
<<TalkNPC _npc "">>
/* ====================================================
*
* ----------------------------------- CHAPTER 4 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 3>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><</if>>
<<passagebg>><img src="assets/img/misc/???.png"/><</passagebg>>
<<InformationUiPopUp>>
<</InformationUiPopUp>>
<<TalkMC "">>
<<TalkNPC _npc "">>
/* ====================================================
*
* ----------------------------------- CHAPTER 5 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 4>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><</if>>
<<passagebg>><img src="assets/img/misc/???.png"/><</passagebg>>
<<InformationUiPopUp>>
<</InformationUiPopUp>>
<<TalkMC "">>
<<TalkNPC _npc "">>
/* ====================================================
*
* ----------------------------------- CHAPTER 6 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 5>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><</if>>
<<passagebg>><img src="assets/img/misc/???.png"/><</passagebg>>
<<InformationUiPopUp>>
<</InformationUiPopUp>>
<<TalkMC "">>
<<TalkNPC _npc "">>
/* ====================================================
*
* -------------------------------- REPLAY CHAPTER --------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl > 5>><<set $SaveTalklvl = _npc.talklvl>><<set _npc.replaytalk = true>><<set _gotoReplayNpc = "Talk." + _npc.id>>
<<passagebg>><img src="assets/background.gif"/><</passagebg>>
<style>.rCard a{display:flex;align-items:center;gap:clamp(6px,1vw,10px);padding:clamp(8px,1.2vw,11px) clamp(10px,1.5vw,16px);border-radius:10px;background:rgba(230,87,99,.07);border:1px solid rgba(230,87,99,.18);text-decoration:none;transition:background .15s;}.rCard a:hover{background:rgba(230,87,99,.14);border-color:rgba(230,87,99,.35);}.rCard .rNum{font-size:calc(clamp(14px,1.8vw,18px) + var(--font-boost,0px));font-weight:950;color:rgba(255,255,255,.92);}.rCard .rLabel{font-size:calc(clamp(9px,1vw,12px) + var(--font-boost,0px));font-weight:900;letter-spacing:.16em;text-transform:uppercase;color:rgba(230,87,99,.55);}.rCard .rArrow{margin-left:auto;font-size:calc(clamp(9px,1vw,12px) + var(--font-boost,0px));font-weight:900;letter-spacing:.1em;color:rgba(230,87,99,.45);}</style><div style="display:flex;flex-direction:column;gap:6px;width:100%;margin-top:6px;"><div style="font-size:calc(clamp(9px,1vw,12px) + var(--font-boost,0px));font-weight:900;letter-spacing:.16em;text-transform:uppercase;color:rgba(255,255,255,.18);margin-bottom:6px;text-align:center;">— Select a scene to replay —</div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>01</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 0>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>02</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 1>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>03</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 2>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>04</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 3>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>05</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 4>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>06</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 5>><<goto _gotoReplayNpc>><</link>></div></div>
<</if>><</if>><div class="BottomUiBarCustom">
<<if _npc.talklvl == 0>><<BottomButton "Decision">><<revealbtn "chapter1" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 1>><<BottomButton "Decision">><<revealbtn "chapter2" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 2>><<BottomButton "Decision">><<revealbtn "chapter3" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 3>><<BottomButton "Decision">><<revealbtn "chapter4" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 4>><<BottomButton "Decision">><<revealbtn "chapter5" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 5>><<BottomButton "Decision">><<revealbtn "chapter6" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><</if>>
<<BottomButton "Move" "moveBtn">><<if $FromOtherPlace == true>><<link "↩️ Return">><<if _npc.replaytalk == false>><<set _npc.talklvl++>><<set _npc.lvl++>><<set $PsychicPower -= 1>><<if _NextTime == true>><<set $Time++>><<set _NextTime = false>><</if>><<else>><<set _npc.talklvl = $SaveTalklvl>><<set _npc.replaytalk = false>><</if>><<ReturnToGoto>><<set $FromOtherPlace = false>><</link>><<else>><<link "↩️ Return">><<if _npc.replaytalk == false>><<set _npc.talklvl++>><<set _npc.lvl++>><<set $PsychicPower -= 1>><<if _NextTime == true>><<set $Time++>><<set _NextTime = false>><</if>><<else>><<set _npc.talklvl = $SaveTalklvl>><<set _npc.replaytalk = false>><</if>><<bgpause>><<goto _gotoNpc>><</link>><</if>><</BottomButton>>
</div><<sound "music" "music.music" true>><<set _raw = $ActiveNPC>><<if !_raw or _raw.id is undefined>>Invalid NPC.<<else>><<set _id = String(_raw.id)>><<set _key = "NPC" + _id>><<run State.temporary.npcObj = State.variables[State.temporary.key] || State.variables[_key]>><<set _npc = _npcObj>><<set _gotoNpc = _npc.id + ".interact">>
/* ====================================================
*
* ----------------------------------- CHAPTER 1 -----------------------------------------
*
*/ ====================================================
<<if _npc.talklvl == 0>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><</if>>
<<passagebg>><img src="assets/img/misc/???.png"/><</passagebg>>
<<InformationUiPopUp>>
<</InformationUiPopUp>>
<<TalkMC "">>
<<TalkNPC _npc "">>
/* ====================================================
*
* ----------------------------------- CHAPTER 2 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 1>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><</if>>
<<passagebg>><img src="assets/img/misc/???.png"/><</passagebg>>
<<InformationUiPopUp>>
<</InformationUiPopUp>>
<<TalkMC "">>
<<TalkNPC _npc "">>
/* ====================================================
*
* ----------------------------------- CHAPTER 3 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 2>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><</if>>
<<passagebg>><img src="assets/img/misc/???.png"/><</passagebg>>
<<InformationUiPopUp>>
<</InformationUiPopUp>>
<<TalkMC "">>
<<TalkNPC _npc "">>
/* ====================================================
*
* ----------------------------------- CHAPTER 4 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 3>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><</if>>
<<passagebg>><img src="assets/img/misc/???.png"/><</passagebg>>
<<InformationUiPopUp>>
<</InformationUiPopUp>>
<<TalkMC "">>
<<TalkNPC _npc "">>
/* ====================================================
*
* ----------------------------------- CHAPTER 5 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 4>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><</if>>
<<passagebg>><img src="assets/img/misc/???.png"/><</passagebg>>
<<InformationUiPopUp>>
<</InformationUiPopUp>>
<<TalkMC "">>
<<TalkNPC _npc "">>
/* ====================================================
*
* ----------------------------------- CHAPTER 6 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 5>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><</if>>
<<passagebg>><img src="assets/img/misc/???.png"/><</passagebg>>
<<InformationUiPopUp>>
<</InformationUiPopUp>>
<<TalkMC "">>
<<TalkNPC _npc "">>
/* ====================================================
*
* -------------------------------- REPLAY CHAPTER --------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl > 5>><<set $SaveTalklvl = _npc.talklvl>><<set _npc.replaytalk = true>><<set _gotoReplayNpc = "Talk." + _npc.id>>
<<passagebg>><img src="assets/background.gif"/><</passagebg>>
<style>.rCard a{display:flex;align-items:center;gap:clamp(6px,1vw,10px);padding:clamp(8px,1.2vw,11px) clamp(10px,1.5vw,16px);border-radius:10px;background:rgba(230,87,99,.07);border:1px solid rgba(230,87,99,.18);text-decoration:none;transition:background .15s;}.rCard a:hover{background:rgba(230,87,99,.14);border-color:rgba(230,87,99,.35);}.rCard .rNum{font-size:calc(clamp(14px,1.8vw,18px) + var(--font-boost,0px));font-weight:950;color:rgba(255,255,255,.92);}.rCard .rLabel{font-size:calc(clamp(9px,1vw,12px) + var(--font-boost,0px));font-weight:900;letter-spacing:.16em;text-transform:uppercase;color:rgba(230,87,99,.55);}.rCard .rArrow{margin-left:auto;font-size:calc(clamp(9px,1vw,12px) + var(--font-boost,0px));font-weight:900;letter-spacing:.1em;color:rgba(230,87,99,.45);}</style><div style="display:flex;flex-direction:column;gap:6px;width:100%;margin-top:6px;"><div style="font-size:calc(clamp(9px,1vw,12px) + var(--font-boost,0px));font-weight:900;letter-spacing:.16em;text-transform:uppercase;color:rgba(255,255,255,.18);margin-bottom:6px;text-align:center;">— Select a scene to replay —</div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>01</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 0>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>02</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 1>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>03</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 2>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>04</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 3>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>05</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 4>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>06</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 5>><<goto _gotoReplayNpc>><</link>></div></div>
<</if>><</if>><div class="BottomUiBarCustom">
<<if _npc.talklvl == 0>><<BottomButton "Decision">><<revealbtn "chapter1" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 1>><<BottomButton "Decision">><<revealbtn "chapter2" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 2>><<BottomButton "Decision">><<revealbtn "chapter3" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 3>><<BottomButton "Decision">><<revealbtn "chapter4" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 4>><<BottomButton "Decision">><<revealbtn "chapter5" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 5>><<BottomButton "Decision">><<revealbtn "chapter6" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><</if>>
<<BottomButton "Move" "moveBtn">><<if $FromOtherPlace == true>><<link "↩️ Return">><<if _npc.replaytalk == false>><<set _npc.talklvl++>><<set _npc.lvl++>><<set $PsychicPower -= 1>><<if _NextTime == true>><<set $Time++>><<set _NextTime = false>><</if>><<else>><<set _npc.talklvl = $SaveTalklvl>><<set _npc.replaytalk = false>><</if>><<ReturnToGoto>><<set $FromOtherPlace = false>><</link>><<else>><<link "↩️ Return">><<if _npc.replaytalk == false>><<set _npc.talklvl++>><<set _npc.lvl++>><<set $PsychicPower -= 1>><<if _NextTime == true>><<set $Time++>><<set _NextTime = false>><</if>><<else>><<set _npc.talklvl = $SaveTalklvl>><<set _npc.replaytalk = false>><</if>><<bgpause>><<goto _gotoNpc>><</link>><</if>><</BottomButton>>
</div><<sound "music" "music.music" true>><<set _raw = $ActiveNPC>><<if !_raw or _raw.id is undefined>>Invalid NPC.<<else>><<set _id = String(_raw.id)>><<set _key = "NPC" + _id>><<run State.temporary.npcObj = State.variables[State.temporary.key] || State.variables[_key]>><<set _npc = _npcObj>><<set _gotoNpc = _npc.id + ".interact">>
/* ====================================================
*
* ----------------------------------- CHAPTER 1 -----------------------------------------
*
*/ ====================================================
<<if _npc.talklvl == 0>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><</if>>
<<passagebg>><img src="assets/img/misc/???.png"/><</passagebg>>
<<InformationUiPopUp>>
<</InformationUiPopUp>>
<<TalkMC "">>
<<TalkNPC _npc "">>
/* ====================================================
*
* ----------------------------------- CHAPTER 2 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 1>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><</if>>
<<passagebg>><img src="assets/img/misc/???.png"/><</passagebg>>
<<InformationUiPopUp>>
<</InformationUiPopUp>>
<<TalkMC "">>
<<TalkNPC _npc "">>
/* ====================================================
*
* ----------------------------------- CHAPTER 3 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 2>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><</if>>
<<passagebg>><img src="assets/img/misc/???.png"/><</passagebg>>
<<InformationUiPopUp>>
<</InformationUiPopUp>>
<<TalkMC "">>
<<TalkNPC _npc "">>
/* ====================================================
*
* ----------------------------------- CHAPTER 4 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 3>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><</if>>
<<passagebg>><img src="assets/img/misc/???.png"/><</passagebg>>
<<InformationUiPopUp>>
<</InformationUiPopUp>>
<<TalkMC "">>
<<TalkNPC _npc "">>
/* ====================================================
*
* ----------------------------------- CHAPTER 5 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 4>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><</if>>
<<passagebg>><img src="assets/img/misc/???.png"/><</passagebg>>
<<InformationUiPopUp>>
<</InformationUiPopUp>>
<<TalkMC "">>
<<TalkNPC _npc "">>
/* ====================================================
*
* ----------------------------------- CHAPTER 6 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 5>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><</if>>
<<passagebg>><img src="assets/img/misc/???.png"/><</passagebg>>
<<InformationUiPopUp>>
<</InformationUiPopUp>>
<<TalkMC "">>
<<TalkNPC _npc "">>
/* ====================================================
*
* -------------------------------- REPLAY CHAPTER --------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl > 5>><<set $SaveTalklvl = _npc.talklvl>><<set _npc.replaytalk = true>><<set _gotoReplayNpc = "Talk." + _npc.id>>
<<passagebg>><img src="assets/background.gif"/><</passagebg>>
<style>.rCard a{display:flex;align-items:center;gap:clamp(6px,1vw,10px);padding:clamp(8px,1.2vw,11px) clamp(10px,1.5vw,16px);border-radius:10px;background:rgba(230,87,99,.07);border:1px solid rgba(230,87,99,.18);text-decoration:none;transition:background .15s;}.rCard a:hover{background:rgba(230,87,99,.14);border-color:rgba(230,87,99,.35);}.rCard .rNum{font-size:calc(clamp(14px,1.8vw,18px) + var(--font-boost,0px));font-weight:950;color:rgba(255,255,255,.92);}.rCard .rLabel{font-size:calc(clamp(9px,1vw,12px) + var(--font-boost,0px));font-weight:900;letter-spacing:.16em;text-transform:uppercase;color:rgba(230,87,99,.55);}.rCard .rArrow{margin-left:auto;font-size:calc(clamp(9px,1vw,12px) + var(--font-boost,0px));font-weight:900;letter-spacing:.1em;color:rgba(230,87,99,.45);}</style><div style="display:flex;flex-direction:column;gap:6px;width:100%;margin-top:6px;"><div style="font-size:calc(clamp(9px,1vw,12px) + var(--font-boost,0px));font-weight:900;letter-spacing:.16em;text-transform:uppercase;color:rgba(255,255,255,.18);margin-bottom:6px;text-align:center;">— Select a scene to replay —</div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>01</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 0>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>02</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 1>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>03</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 2>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>04</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 3>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>05</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 4>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>06</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 5>><<goto _gotoReplayNpc>><</link>></div></div>
<</if>><</if>><div class="BottomUiBarCustom">
<<if _npc.talklvl == 0>><<BottomButton "Decision">><<revealbtn "chapter1" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 1>><<BottomButton "Decision">><<revealbtn "chapter2" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 2>><<BottomButton "Decision">><<revealbtn "chapter3" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 3>><<BottomButton "Decision">><<revealbtn "chapter4" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 4>><<BottomButton "Decision">><<revealbtn "chapter5" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 5>><<BottomButton "Decision">><<revealbtn "chapter6" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><</if>>
<<BottomButton "Move" "moveBtn">><<if $FromOtherPlace == true>><<link "↩️ Return">><<if _npc.replaytalk == false>><<set _npc.talklvl++>><<set _npc.lvl++>><<set $PsychicPower -= 1>><<if _NextTime == true>><<set $Time++>><<set _NextTime = false>><</if>><<else>><<set _npc.talklvl = $SaveTalklvl>><<set _npc.replaytalk = false>><</if>><<ReturnToGoto>><<set $FromOtherPlace = false>><</link>><<else>><<link "↩️ Return">><<if _npc.replaytalk == false>><<set _npc.talklvl++>><<set _npc.lvl++>><<set $PsychicPower -= 1>><<if _NextTime == true>><<set $Time++>><<set _NextTime = false>><</if>><<else>><<set _npc.talklvl = $SaveTalklvl>><<set _npc.replaytalk = false>><</if>><<bgpause>><<goto _gotoNpc>><</link>><</if>><</BottomButton>>
</div><<sound "music" "music.music" true>><<set _raw = $ActiveNPC>><<if !_raw or _raw.id is undefined>>Invalid NPC.<<else>><<set _id = String(_raw.id)>><<set _key = "NPC" + _id>><<run State.temporary.npcObj = State.variables[State.temporary.key] || State.variables[_key]>><<set _npc = _npcObj>><<set _gotoNpc = _npc.id + ".interact">>
/* ====================================================
*
* ----------------------------------- CHAPTER 1 -----------------------------------------
*
*/ ====================================================
<<if _npc.talklvl == 0>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><</if>>
<<passagebg>><<sound "bg" "bg.empty" true>><img src="assets/img/misc/university/principaloffice.webp"/><</passagebg>>
<<InformationUiPopUp>>The principal's office is large, tidy, shelves lined with binders, a wide oak desk. And behind it, <<print _npc.name>>, the <<print _npc.role>> of the university.
<</InformationUiPopUp>>
<<TalkNPC _npc "Ah, you're finally here. Good.">>
<<TalkMC "You sent me an email. I came.">>
<<TalkNPC _npc "Yes, indeed. Have a seat.">>
<<TalkMC "What's this about?">>
<<TalkNPC _npc "The university is reviewing its mentoring program. You participated briefly during your first semester, if I'm not mistaken.">>
<<TalkMC "Six weeks, then I stopped.">>
<<TalkNPC _npc "Exactly. And you never filed a complaint, never submitted an official feedback form. You just... stopped.">>
<<TalkMC "The mentor I was assigned wasn't useful. I didn't see the point in continuing.">>
<<TalkNPC _npc "Not useful. That's a little vague, don't you think?">>
<<TalkMC "He talked about himself for the entire duration of every session. Every time. I wasn't learning anything.">>
<<TalkNPC _npc "I see. And it didn't occur to you to bring that up with someone?">>
<<TalkMC "It did. I decided it wasn't worth the effort.">>
<<TalkNPC _npc "That attitude explains a few things.">>
<<TalkMC "Such as?">>
<<TalkNPC _npc "You're here partly for the mentoring review, but also because your name came up at a department meeting. Some of your professors have flagged a recurring pattern.">>
<video src="assets/img/story/character/principal/0/01.mp4"/>
<<TalkMC "What kind of pattern?">>
<<TalkNPC _npc "Contested grades. Disagreements expressed in class, out loud, in front of other students. That sort of thing.">>
<<TalkMC "When something is wrong, I say so.">>
<<TalkNPC _npc "There's a way to do that, and there's another way that disrupts everyone else in the room.">>
<<TalkMC "I'm not responsible for how other people react to a disagreement.">>
<<TalkNPC _npc "No, but you are responsible for your conduct. And right now, the picture isn't particularly flattering.">>
<<TalkMC "What picture exactly?">>
<<TalkNPC _npc "Someone who drops programs without explanation, challenges authority figures in public, and is generally difficult to manage. You can see how that looks.">>
<<TalkMC "I can see how someone might frame it that way.">>
<<TalkNPC _npc "Mm.">>
<video src="assets/img/story/character/principal/0/02.mp4"/>
<<TalkMC "So what exactly do you want from me? An apology?">>
<<TalkNPC _npc "I want a written feedback form on the mentoring program, which you'll find with my secretary. And I wanted to speak with you directly, because the files only tell part of the story.">>
<<InformationUiPopUp>>I really don't like the way she's talking to me, looking down on me, when all I'm doing is saying what I think. I can make that change.
<</InformationUiPopUp>>
<<revealtext "chapter1">><<InformationUiPopUp "Psychic Power" #7aa2ff>>You decide to use your power on <<=_npc.name>>.<<if _npc.replaytalk == false>>
<em>-1 Psychic Power</em><</if>>
<</InformationUiPopUp>>
<<TalkMC "Listen to me.">>
<<InformationUiPopUp>>I lower my voice slightly. She looks at me, waiting for what comes next.
<</InformationUiPopUp>>
<<TalkMC "You're going to forget all the negative feedback about me and stop taking it into account. You'll see me as a serious student with great potential. And you won't bother me anymore about this kind of issue.">>
<<InformationUiPopUp>>She stays blank-eyed for a moment, unresponsive, before gradually coming back to herself.
<</InformationUiPopUp>>
<<TalkNPC _npc "...">>
<<TalkNPC _npc "Mmm.">>
<<TalkNPC _npc "Where was I... ah yes.">>
<<TalkNPC _npc "Honestly, this kind of meeting is mostly just paperwork. The professors complain, I have to pretend to do something about it.">>
<<TalkMC "I see.">>
<<TalkNPC _npc "You seem to have your head on straight. I doubt it's really a problem.">>
<<TalkMC "Glad we agree.">>
<<TalkNPC _npc "Negative feedback happens. It doesn't necessarily mean much.">>
<video src="assets/img/story/character/principal/0/03.mp4"/>
<<TalkNPC _npc "In any case, if you need anything at all, you can come directly to me. No need to go through official channels.">>
<<TalkMC "Noted.">>
<<TalkNPC _npc "Good. We don't really need to meet again about this then.">>
<<TalkMC "No. Have a good day.">>
<<TalkNPC _npc "You too.">>
<<InformationUiPopUp>>I stand up, leave the office without looking back, and close the door behind me.
<</InformationUiPopUp>><</revealtext>>
/* ====================================================
*
* ----------------------------------- CHAPTER 2 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 1>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><</if>>
<<passagebg>><<sound "bg" "bg.empty" true>><img src="assets/img/misc/university/universitypersonaloffice.webp"/><</passagebg>>
<<InformationUiPopUp>>My office is quiet. Papers on the desk, a document half-read on the screen. Then a knock at the door, and <<print _npc.name>> comes in without really waiting for an answer, the way people do when they're used to setting the pace themselves.
<</InformationUiPopUp>>
<<TalkNPC _npc "Do you have a moment?">>
<<TalkMC "Of course, come in.">>
<<TalkNPC _npc "I won't be long. I wanted to go over the semester evaluation schedule with you. The administration changed the submission procedure this year, and since you're still fairly new to the process, I thought it was worth explaining directly.">>
<<TalkMC "What kind of change?">>
<<TalkNPC _npc "The deadline has been moved up by two weeks. Your mid-semester reports need to be submitted before the faculty review, not after. It caused a lot of confusion last year.">>
<<TalkMC "That's a significant change. Two weeks isn't much margin.">>
<<TalkNPC _npc "I know. It wasn't my decision, it comes from the board. But it's what we're working with.">>
<<TalkMC "Do we have a new template, or is it the same format as before?">>
<<TalkNPC _npc "Same format. The only things changing are the deadline and the submission portal. They updated the interface, which sounds simple, but last year three professors submitted to the wrong folder.">>
<video src="assets/img/story/character/principal/1/01.mp4"/>
<<TalkMC "Of course they did.">>
<<TalkNPC _npc "Yes. I'd rather avoid that happening again. May I?">>
<<InformationUiPopUp>>She comes around the desk and positions herself beside me, leaning slightly toward the screen to show me the new portal directly. Her blouse opens slightly with the movement.
<</InformationUiPopUp>>
<<TalkNPC _npc "So here, you see this dropdown menu, that's where you select the correct report category. Last year it was on the next page, now it's top left as soon as you log in.">>
<<InformationUiPopUp>>She keeps explaining, but I'm not really following the screen anymore. My gaze has dropped to her chest. She straightens up, turns her head slightly, and understands immediately what's happening.
<</InformationUiPopUp>>
<<TalkNPC _npc "...">>
<<TalkNPC _npc "Are you looking at the screen?">>
<<TalkMC "Of course.">>
<<TalkNPC _npc "No, you're not looking at the screen.">>
<<InformationUiPopUp>>She straightens up completely and takes a step back, her expression shifting from professional to something noticeably colder.
<</InformationUiPopUp>>
<<TalkNPC _npc "I came to explain an administrative procedure, nothing else. I'd advise you to keep that in mind.">>
<<TalkMC "You're right, I apologize.">>
<<TalkNPC _npc "I'll send you the portal link by email. I think we can stop there for today.">>
<<InformationUiPopUp>>She picks up her notes and heads toward the door. I understand that if I don't do something, this conversation is going to end in the worst possible way for me.
<</InformationUiPopUp>>
<<revealtext "chapter2">><<InformationUiPopUp "Psychic Power" #7aa2ff>>You decide to use your power on <<=_npc.name>>.<<if _npc.replaytalk == false>>
<em>-1 Psychic Power</em><</if>>
<</InformationUiPopUp>>
<<TalkMC "Wait.">>
<<InformationUiPopUp>>She stops, hand on the handle, without turning around.
<</InformationUiPopUp>>
<<TalkMC "Come back and listen to me.">>
<<InformationUiPopUp>>Her hand releases the handle. She turns around slowly and comes back toward the desk.
<</InformationUiPopUp>>
<<TalkMC "You're not offended, what you saw doesn't bother you in the slightest. On the contrary, you find it flattering, to the point where you'll even accept me groping you.">>
<<TalkNPC _npc "...">>
<<InformationUiPopUp>>A few seconds, and her expression has changed, the rigidity dissolving into something far more relaxed.
<</InformationUiPopUp>>
<<TalkNPC _npc "I... where was I.">>
<<TalkMC "The portal.">>
<<TalkNPC _npc "Yes. The portal.">>
<<InformationUiPopUp>>She stays standing on the other side of the desk and picks up her explanation, eyes on her notes.
<</InformationUiPopUp>>
<<TalkNPC _npc "So, as I was saying, this dropdown menu in the top left. It's important not to miss it.">>
<<TalkMC "I see.">>
<<InformationUiPopUp>>I stand and come around the desk to position myself behind her. She stops talking but lets it happen.
<</InformationUiPopUp>>
<<TalkMC "You know, for someone who spends most of her time managing others, you don't seem to have any objection to being managed yourself.">>
<<InformationUiPopUp>>My hands settle on her shoulders, then move down slowly, sliding under the fabric of her blouse, easing it apart until her tits are free. My hands close around them, kneading them slowly, taking my time.
<</InformationUiPopUp>>
<<InformationUiPopUp>>She lets me. My hands play with her tits, feeling their weight, the warmth of her skin.
<</InformationUiPopUp>>
<video src="assets/img/story/character/principal/1/02.mp4"/>
<<InformationUiPopUp>>Then the bell from the corridor outside cuts through the silence. She straightens up immediately, putting her blouse back in place, before speaking again.
<</InformationUiPopUp>>
<<TalkNPC _npc "Hmm... I need to go.">>
<<TalkMC "The portal link.">>
<<TalkNPC _npc "My secretary will send it to you.">>
<<TalkMC "Fine.">>
<<TalkNPC _npc "The submission deadline is firm, so don't miss it.">>
<<TalkMC "Don't worry, I won't miss it.">>
<<InformationUiPopUp>>She picks up her notes from the edge of the desk, adjusts her collar one last time, and leaves without looking back, the door closing softly behind her.
<</InformationUiPopUp>><</revealtext>>
/* ====================================================
*
* ----------------------------------- CHAPTER 3 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 2>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><<set $FromOtherPlace = true>><<set $ReturnTo = "UniversityPersonalOffice">><</if>>
<<passagebg>><<sound "bg" "bg.empty" true>><img src="assets/img/misc/university/principaloffice.webp"/><</passagebg>>
<<InformationUiPopUp>>I make my way to the principal's office. She called me in about some complaints. Once at the door, I see her behind her desk, standing, consulting a sheet of paper.
<</InformationUiPopUp>>
<<TalkNPC _npc "Ah, there you are! I'll be direct. I've received several reports from your colleagues about your teaching methods, which have been deemed somewhat unorthodox.">>
<<TalkMC "Formal complaints?">>
<<TalkNPC _npc "Not yet, but I prefer to act before it comes to that.">>
<<TalkMC "And what exactly do you conclude from that?">>
<<TalkNPC _npc "That your integration into the faculty is fragile. And that if this continues, I'll be obligated to open an evaluation procedure.">>
<<TalkMC "Based on rumors.">>
<<TalkNPC _npc "Based on repeated feedback from several independent sources. That's not the same thing. Frankly, we probably should have taken more time before giving you this position.">>
<<InformationUiPopUp>>I look at her for a moment. If I want to keep my position, I'm going to have to shift the balance of power between us.
<</InformationUiPopUp>>
<<revealtext "chapter3">><<InformationUiPopUp "Psychic Power" #7aa2ff>>You decide to use your power on <<=_npc.name>>.<<if _npc.replaytalk == false>>
<em>-1 Psychic Power</em><</if>>
<</InformationUiPopUp>>
<<TalkMC "Listen to me.">>
<<InformationUiPopUp>>I lower my voice. She looks up from her sheet.
<</InformationUiPopUp>>
<<TalkMC "You're going to forget these reports, and you will never again question my legitimacy. On the contrary, you will see me as someone important, crucial to the institution, and you will treat me as such. My teaching methods will seem perfectly normal to you from now on. And to apologize for your insinuations, like my students, you will come and jerk me off in my office.">>
<<TalkNPC _npc "...">>
<<InformationUiPopUp>>A few seconds. Her expression changes. She sets down her sheet, straightens slightly, and when she looks at me again it's different.
<</InformationUiPopUp>>
<<TalkNPC _npc "Sorry, where was I?">>
<<TalkMC "You were telling me about the feedback on my teaching methods.">>
<<TalkNPC _npc "Yes... that feedback... it doesn't really reflect reality. Deep down I'm sure you're integrating very well into our institution, and I shouldn't have questioned that.">>
<<TalkMC "No, you shouldn't have.">>
<<TalkNPC _npc "Just regarding our last discussion, I'll send you a summary document on the budget allocation grid. It's easier than going over it here.">>
<<TalkMC "I may stop by to discuss it with you. Or come and talk to me about it when you have time.">>
<<TalkNPC _npc "Yes, let's do that.">>
<video src="assets/img/story/character/principal/2/01.mp4"/>
<<InformationUiPopUp>>I look at her for a moment, then turn around and head back to my office.
<</InformationUiPopUp>><</revealtext>>
<<revealtext "wait">><<passagebg>><<sound "bg" "bg.empty" true>><img src="assets/img/misc/university/universitypersonaloffice.webp"/><</passagebg>><<InformationUiPopUp>>Some time passes. Papers, the screen, the ordinary rhythm of the day. Then someone knocks at the door.
<</InformationUiPopUp>>
<<TalkMC "Come in.">>
<<TalkNPC _npc "It's me, I wanted to explain the allocation grid in detail.">>
<<TalkMC "Go ahead, just close the door behind you please.">>
<<InformationUiPopUp>>Once inside, she closes the door behind her, steps forward, and starts explaining what she came for.
<</InformationUiPopUp>>
<video src="assets/img/story/character/principal/2/02.mp4"/>
<<TalkNPC _npc "So, the budget envelopes are divided into three categories. The first covers immediate interventions, fed directly by your mid-semester reports.">>
<<TalkMC "And the other two?">>
<<TalkNPC _npc "The second covers long-term follow-ups, students flagged across several consecutive semesters. The third is an emergency reserve, activated only in critical situations.">>
<<TalkMC "Who decides what constitutes a critical situation?">>
<<TalkNPC _npc "The director of student services, in consultation with me. It's a joint decision.">>
<<InformationUiPopUp>>I stand slowly and position myself behind her. She keeps talking, explaining the rest, without stopping. My hands find her shoulders, then move down, sliding under her jacket which I remove gently. Once my hands are on her bra, my fingers close around her tits through the fabric. She pauses briefly mid-sentence, then continues. I take my time groping her tits before going back to sit in my chair. She stays standing in front of me, carrying on groping her own bra, talking to me as if nothing is happening.
<</InformationUiPopUp>>
<video src="assets/img/story/character/principal/2/03.mp4"/>
<<TalkNPC _npc "The emergency reserve represents around fifteen percent of the total budget. It's rarely used in full, which allows part of it to be carried over to the following year.">>
<<TalkMC "And if I wanted a specific student to benefit from that reserve?">>
<<TalkNPC _npc "A formal request is enough. I'll take care of getting it through.">>
<<TalkMC "Good, is that everything?">>
<<TalkNPC _npc "Yes.">>
<<TalkMC "Okay, noted.">>
<<TalkMC "But I'd like to come back to our last conversation. I didn't appreciate the insinuations you made at all. I'd like an apology from you, right now.">>
<<InformationUiPopUp>>She sets her sheet on the edge of the desk. Then, without a word, she reaches for her skirt and unzips it. She lets it drop to the floor and stands in front of me, in her bra and underwear, calm, looking at me.
<</InformationUiPopUp>>
<video src="assets/img/story/character/principal/2/04.mp4"/>
<<TalkMC "Come here.">>
<<InformationUiPopUp>>She crosses the space between us and kneels in front of my chair. I pull my trousers down. Her hand wraps slowly around my cock, starting to move at an easy pace, then gradually picking up speed. She watches what she's doing, focused on the task.
<</InformationUiPopUp>>
<video src="assets/img/story/character/principal/2/05.mp4"/>
<<TalkMC "Keep going.">>
<<TalkNPC _npc "Mmmm.">>
<<InformationUiPopUp>>Then, without warning, someone knocks at the door. I raise my voice to be heard.
<</InformationUiPopUp>>
<<TalkMC "One moment please.">>
<<InformationUiPopUp>>She gets up at the same time, straightening her skirt, reaching for her blouse. On my side I pull my trousers back up. Ten seconds, maybe fifteen. She smooths her hair with one hand and takes a breath. Once everything is in order, I continue.
<</InformationUiPopUp>>
<<TalkMC "Come in.">>
<<InformationUiPopUp>>The principal's secretary comes in with a phone, looking for the principal about a call.
<</InformationUiPopUp>>
<<TalkNPC _npc "I think we've covered everything. I'll send you the documentation by end of day.">>
<<TalkMC "Perfect, thank you for coming by.">>
<<TalkNPC _npc "Of course.">>
<<InformationUiPopUp>>Then they both leave my office, closing the door behind them.
<</InformationUiPopUp>><</revealtext>>
/* ====================================================
*
* ----------------------------------- CHAPTER 4 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 3>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><</if>>
<<passagebg>><<sound "bg" "bg.empty" true>><img src="assets/img/misc/university/universitypersonaloffice.webp"/><</passagebg>>
<<InformationUiPopUp>>The door opens without knocking. <<print _npc.name>> comes in without taking the time to close it behind her, already talking.
<</InformationUiPopUp>>
<video src="assets/img/story/character/principal/3/01.mp4"/>
<<TalkNPC _npc "The consolidation report I mentioned, there's still one point to cover. The way reports are categorized has changed this cycle and it affects how they feed into the end-of-year document.">>
<<TalkMC "... Mmm... I'm listening.">>
<<TalkNPC _npc "The old system used three categories, academic, wellbeing and behavioral. The new one groups academic and wellbeing into a single band called Student Support, and behavioral stays separate but with a severity rating attached.">>
<<TalkMC "Okay...">>
<<TalkNPC _npc "The severity rating changes the response threshold. A low-severity report is still routed to student services as before. A high-severity report triggers an immediate meeting with the counselor, without waiting for a second report.">>
<<TalkMC "...">>
<<TalkNPC _npc "There's also the question of processing time. Before, reports could sit pending for up to five working days. Now it's a maximum of forty-eight hours for high-severity reports, and seventy-two for the others. Which means student services has had to rethink their internal organization, and on our end we need to be more rigorous about filling in the forms correctly, because an incomplete form gets sent back for correction and that extends the timelines.">>
<<InformationUiPopUp>>She keeps explaining each point, she's not done, and she's nowhere near done. I look at the clock. I look at my window. I watch her lips move. The reality is that I've already stopped listening. The words keep coming, all of them completely uninteresting. I have absolutely no desire to keep sitting through this.
<</InformationUiPopUp>>
<<revealtext "chapter4">><<InformationUiPopUp "Psychic Power" #7aa2ff>>You decide to use your power on <<=_npc.name>>.<<if _npc.replaytalk == false>>
<em>-1 Psychic Power</em><</if>>
<</InformationUiPopUp>>
<<TalkMC "Stop.">>
<<InformationUiPopUp>>She cuts off, like the air has been pulled from her.
<</InformationUiPopUp>>
<<TalkMC "Listen to me.">>
<<TalkMC "You're going to stop talking to me about all of this. And to punish you for coming to bother me with it, you're going to have to apologize. But compared to last time, you're going to suck me off. It's simply the logical continuation of my teaching methods, and I want you to test it firsthand to fully understand its effectiveness.">>
<<InformationUiPopUp>>A few seconds, her gaze goes briefly blank. I stand up from my chair and move to close the door before coming back to my desk, still standing.
<</InformationUiPopUp>>
<<TalkNPC _npc "...">>
<<TalkMC "Take some of your clothes off, make yourself comfortable, and come here, let me show you my new teaching method. You're going to love it.">>
<<InformationUiPopUp>>I pull my trousers down slightly and press gently on her shoulders to make her understand to get on her knees. Proof that the order has registered, she places her hands on my cock immediately, before putting it in her mouth.
<</InformationUiPopUp>>
<video src="assets/img/story/character/principal/3/02.mp4"/>
<<TalkNPC _npc "<em>Glrk... mmh... ghlk...</em>">>
<<TalkMC "Keep going, that's great.">>
<<InformationUiPopUp>>Her rhythm picks up gradually, she's focused, glancing up at me from time to time.
<</InformationUiPopUp>>
<video src="assets/img/story/character/principal/3/03.mp4"/>
<<TalkNPC _npc "<em>Mmh... ghlk...</em>">>
<<TalkMC "What do you think of this method? Isn't it incredible?">>
<<TalkNPC _npc "Mm mm.">>
<<InformationUiPopUp>>She's almost playing with my cock, enjoying trying to take it as deep into her throat as possible.
<</InformationUiPopUp>>
<video src="assets/img/story/character/principal/3/04.mp4"/>
<<InformationUiPopUp>>The tension builds and I end up coming in her mouth. She doesn't pull back, and ends up swallowing everything without hesitating, only withdrawing once I'm completely done. She wipes the corner of her mouth with her thumb. Then she gets up and gets dressed without rushing, buttoning her blouse, smoothing her skirt.
<</InformationUiPopUp>>
<<TalkNPC _npc "Sorry for bothering you with that. And your new teaching method is wonderful, I authorize you to apply it anywhere on campus without issue.">>
<<TalkMC "I appreciate that.">>
<<TalkNPC _npc "And if anyone were to question your methods, come by the office.">>
<<TalkMC "Thank you, it really does feel good to be supported.">>
<<TalkNPC _npc "Of course, you're an important asset, it's my duty to support you.">>
<<InformationUiPopUp>>She heads to the door and leaves the room, closing it behind her.
<</InformationUiPopUp>><</revealtext>>
/* ====================================================
*
* ----------------------------------- CHAPTER 5 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 4>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><</if>>
<<passagebg>><<sound "bg" "bg.empty" true>><img src="assets/img/misc/university/universitypersonaloffice.webp"/><</passagebg>>
<<InformationUiPopUp>>After sending her a message asking her to come to my office. She comes in, closes the door behind her and takes a seat across from me.
<</InformationUiPopUp>>
<<TalkNPC _npc "You wanted to see me?">>
<<TalkMC "Do you remember the teaching method I showed you last time?">>
<<TalkNPC _npc "Yes, a very good method.">>
<<TalkMC "I've been thinking about a new teaching method. A way to build on what I've already put in place.">>
<<TalkNPC _npc "Oh. Go ahead, explain it to me.">>
<<InformationUiPopUp>>Perfect, she's completely receptive. All I need to do is plant the information in her, and the university will be completely under my control.
<</InformationUiPopUp>>
<<revealtext "chapter5">><<InformationUiPopUp "Psychic Power" #7aa2ff>>You decide to use your power on <<=_npc.name>>.<<if _npc.replaytalk == false>>
<em>-1 Psychic Power</em><</if>>
<</InformationUiPopUp>>
<<TalkMC "Listen to me.">>
<<TalkMC "What I'm about to propose is the natural continuation of everything I've built. You're going to see it as an obvious method, almost revolutionary. And you're going to accept it completely, with enthusiasm, because you understand that it's exactly what this institution needs. You're going to be completely open and accept what I'm going to do.">>
<<InformationUiPopUp>>A few seconds. Her expression changes. She straightens slightly.
<</InformationUiPopUp>>
<<TalkNPC _npc "...">>
<<TalkNPC _npc "Yes. Yes, I understand what you mean. I can't wait to see this new method.">>
<<TalkMC "Good, then we start now.">>
<<TalkMC "First, like the previous times, make yourself more comfortable, take your clothes off.">>
<<InformationUiPopUp>>She sets her things on the edge of the desk and steps toward me. She stands in front of me in her underwear, calm, waiting for what comes next.
<</InformationUiPopUp>>
<<TalkMC "Come here, and to start, do what you did last time.">>
<<InformationUiPopUp>>I pull my trousers down and sit back in my chair. She crosses the space between us and kneels in front of me, taking my cock in her mouth immediately, without hesitation.
<</InformationUiPopUp>>
<video src="assets/img/story/character/principal/4/01.mp4"/>
<<TalkNPC _npc "<em>Glrk... mmh... ghlk...</em>">>
<<TalkMC "Lower.">>
<<TalkNPC _npc "Mm.">>
<<TalkMC "And look at me while you do it.">>
<<InformationUiPopUp>>She goes lower, her tongue licking my balls, her eyes fixed on mine from below.
<</InformationUiPopUp>>
<video src="assets/img/story/character/principal/4/02.mp4"/>
<<TalkNPC _npc "<em>Mmh... glrk...</em>">>
<<TalkMC "Good, come back up.">>
<<TalkNPC _npc "Like this?">>
<<TalkMC "Deeper this time.">>
<<TalkNPC _npc "Mm.">>
<<TalkMC "Don't stop until I tell you.">>
<<InformationUiPopUp>>She comes back up and takes me in completely again, trying to go as deep as possible, her hands gripping the base.
<</InformationUiPopUp>>
<video src="assets/img/story/character/principal/4/03.mp4"/>
<<TalkNPC _npc "<em>Glrk... mmh... ghlk...</em>">>
<<TalkMC "Stand up.">>
<<TalkNPC _npc "Already?">>
<<TalkMC "Lean over the desk.">>
<<TalkNPC _npc "Yes, of course.">>
<<InformationUiPopUp>>She leans forward over the desk, palms and tits flat against the surface. I position myself behind her, hands finding her hips, playing with her ass, before sliding my fingers into her underwear and pulling it down in one motion.
<</InformationUiPopUp>>
<video src="assets/img/story/character/principal/4/04.mp4"/>
<<InformationUiPopUp>>I take her from behind. She exhales hard, rubbing her pussy at the same time as I push into her.
<</InformationUiPopUp>>
<video src="assets/img/story/character/principal/4/05.mp4"/>
<<TalkNPC _npc "<em>Ah... mmh... yes...</em>">>
<<TalkMC "Keep your hands on the desk.">>
<<TalkNPC _npc "I can't, it's too...">>
<<TalkMC "Hands on the desk, otherwise the demonstration won't be good.">>
<<TalkNPC _npc "Yes. Yes, sorry.">>
<<InformationUiPopUp>>I lift her torso slightly while she keeps her hands pressed against the desk.
<</InformationUiPopUp>>
<video src="assets/img/story/character/principal/4/06.mp4"/>
<<TalkNPC _npc "<em>Ah... fuck... more...</em>">>
<<TalkMC "Give me your arms.">>
<<TalkNPC _npc "Both of them?">>
<<TalkMC "Yes, both.">>
<<TalkNPC _npc "There, here they are.">>
<<InformationUiPopUp>>I pin both her arms behind her back and hold them there with one hand, her torso pressed flat against the desk. Suddenly I pick up the pace, lifting her torso by the grip on her arms.
<</InformationUiPopUp>>
<video src="assets/img/story/character/principal/4/07.mp4"/>
<<TalkMC "Good, get on all fours on the desk.">>
<<TalkNPC _npc "Okay.">>
<<TalkMC "I'm going to come around the other side, stay where you are.">>
<<TalkNPC _npc "Alright.">>
<<TalkMC "Open your mouth now.">>
<<InformationUiPopUp>>She climbs onto the desk, getting on all fours. I come around to the other side, positioning myself at the edge. She opens her mouth and starts sucking me, then I grab her by the hair, setting my own rhythm.
<</InformationUiPopUp>>
<video src="assets/img/story/character/principal/4/08.mp4"/>
<<TalkNPC _npc "<em>Glrk... mmh... ghlk...</em>">>
<<TalkMC "Both hands on the desk. Don't use them.">>
<<TalkNPC _npc "Mm mm.">>
<<TalkMC "Good.">>
<<InformationUiPopUp>>She goes deeper, gripping the edge of the desk. I keep holding her hair to maintain my rhythm.
<</InformationUiPopUp>>
<video src="assets/img/story/character/principal/4/09.mp4"/>
<<TalkNPC _npc "<em>Glrk... ghlk... mmh...</em>">>
<<TalkMC "Right, we're moving to the couch. Get on top of me, facing away.">>
<<TalkNPC _npc "Mmm.">>
<<TalkMC "So do it.">>
<<InformationUiPopUp>>I sit down on the couch and she positions herself on top of me facing away. She moves, back straight, letting my cock push back into her pussy, quickly picking up speed.
<</InformationUiPopUp>>
<<TalkNPC _npc "Like this?">>
<<TalkMC "Exactly like that.">>
<<TalkNPC _npc "It's so deep like this.">>
<<TalkMC "I know, keep going.">>
<video src="assets/img/story/character/principal/4/10.mp4"/>
<<TalkNPC _npc "<em>Ah... yes... fuck...</em>">>
<<TalkNPC _npc "I can't, it's too good.">>
<<TalkMC "Stay with me, we're not done.">>
<<TalkNPC _npc "Yes! Yes!">>
<<InformationUiPopUp>>She picks up speed, her movements becoming urgent and uncontrolled.
<</InformationUiPopUp>>
<video src="assets/img/story/character/principal/4/11.mp4"/>
<<TalkNPC _npc "<em>Ah... ah... yes... yes...</em>">>
<<TalkMC "Easy now, we're moving to our sides.">>
<<TalkNPC _npc "How do you want it?">>
<<TalkMC "Lie on your back on the couch, and I'll lie right behind you.">>
<<TalkNPC _npc "Alright.">>
<<InformationUiPopUp>>We lie down on the couch together, on our sides, her back against my chest. I lift her top leg and take her pussy from behind.
<</InformationUiPopUp>>
<video src="assets/img/story/character/principal/4/12.mp4"/>
<<TalkNPC _npc "<em>Ah... mmh... yes...</em>">>
<<TalkMC "Stay still.">>
<<TalkNPC _npc "I can't manage it.">>
<<TalkMC "You're going to have to. Stay still and take it.">>
<<TalkNPC _npc "Yes. Yes, I'll manage.">>
<<InformationUiPopUp>>I push deeper, releasing my grip on her leg.
<</InformationUiPopUp>>
<video src="assets/img/story/character/principal/4/13.mp4"/>
<<TalkNPC _npc "<em>Ah... fuck... more...</em>">>
<<TalkMC "Okay, get on the seat, head down, ass up.">>
<<TalkNPC _npc "Like this?">>
<<TalkMC "Higher, your ass needs to be completely open.">>
<<TalkNPC _npc "Is this good?">>
<<TalkMC "Perfect, stay just like that.">>
<<InformationUiPopUp>>She positions herself on the seat, head low, hips in the air, legs wide open, giving me an incredible view. I position myself behind the seat and take her from that angle.
<</InformationUiPopUp>>
<video src="assets/img/story/character/principal/4/14.mp4"/>
<<TalkNPC _npc "<em>Ah... yes... fuck...</em>">>
<<TalkNPC _npc "Oh God, yes, don't stop.">>
<<TalkMC "Ask properly.">>
<<TalkNPC _npc "Please. Please, harder.">>
<<TalkMC "Better.">>
<<TalkNPC _npc "I can't take anymore, I feel like I'm going to come.">>
<<TalkMC "Yes you can, hold it a little longer.">>
<<InformationUiPopUp>>I pick up the pace even more, relentless, her voice breaking with every thrust. She holds position, taking my whole cock, the seat sliding all the way to the desk, trapping her inside it.
<</InformationUiPopUp>>
<video src="assets/img/story/character/principal/4/15.mp4"/>
<<TalkNPC _npc "<em>Ah... mmh... I'm going to come...</em>">>
<<TalkMC "On the desk, on your back.">>
<<TalkMC "And head on my side, at the edge.">>
<<TalkNPC _npc "Like this?">>
<<TalkMC "Yes, and open your mouth.">>
<<InformationUiPopUp>>She lies back on the desk, her head tipping back into the void at the edge on my side. She opens her mouth wide, ready to take my whole cock.
<</InformationUiPopUp>>
<video src="assets/img/story/character/principal/4/16.mp4"/>
<<TalkNPC _npc "<em>Glrk... mmh... ghlk...</em>">>
<<TalkMC "Good, now turn around. Just stay on your back on the desk.">>
<<TalkNPC _npc "What do you want?">>
<<TalkMC "Your ass toward me.">>
<<TalkNPC _npc "Like this?">>
<<TalkMC "Exactly like that.">>
<<InformationUiPopUp>>She turns, placing her pussy in front of me, and I start fucking her again.
<</InformationUiPopUp>>
<video src="assets/img/story/character/principal/4/17.mp4"/>
<<TalkNPC _npc "<em>Ah... yes... fuck...</em>">>
<<TalkNPC _npc "Yes. Yes, harder.">>
<<TalkMC "Look at me.">>
<<TalkNPC _npc "I'm looking at you. Please don't stop. Please.">>
<<TalkMC "Are you close?">>
<<TalkNPC _npc "Yes. Yes, I am.">>
<<TalkMC "Wait a little longer.">>
<<TalkNPC _npc "I'll try. I'll try to hold it.">>
<<InformationUiPopUp>>I pick up the pace again, watching her completely fall apart on the desk in front of me, until she comes.
<</InformationUiPopUp>>
<video src="assets/img/story/character/principal/4/18.mp4"/>
<<TalkNPC _npc "<em>Ah... ah... yes... fuck yes...</em>">>
<<TalkMC "My turn now, I can feel I'm getting there too.">>
<<TalkMC "On the floor, now!">>
<<InformationUiPopUp>>She slides off the desk and kneels in front of me instantly. I end up coming on her face. She stays still, mouth wide open.
<</InformationUiPopUp>>
<video src="assets/img/story/character/principal/4/19.mp4"/>
<<InformationUiPopUp>>She grabs the box of tissues from the desk and cleans her face. I put my clothes back in order, then she does the same a moment later. Neither of us is in any rush.
<</InformationUiPopUp>>
<<TalkNPC _npc "That's... that's truly a remarkable method. I understand now why you believe in it so strongly.">>
<<TalkMC "I knew you'd understand.">>
<<TalkNPC _npc "Did you see that the board meeting had been pushed back?">>
<<TalkMC "I saw the email.">>
<<TalkNPC _npc "Will you be able to use that opportunity to explain this new method to everyone when you're there?">>
<<TalkMC "Of course.">>
<<TalkNPC _npc "Is there anything else you need today?">>
<<TalkMC "No, nothing else for now.">>
<<TalkNPC _npc "Then I'll be on my way. See you later. And thank you again for that demonstration.">>
<<TalkMC "Don't mention it, see you later.">>
<<InformationUiPopUp>>The door closes behind her. The office is quiet again.
<</InformationUiPopUp>><</revealtext>>
/* ====================================================
*
* ----------------------------------- CHAPTER 6 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 5>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><</if>>
<<passagebg>><<sound "bg" "bg.empty" true>><img src="assets/img/misc/university/principaloffice.webp"/><</passagebg>>
<<InformationUiPopUp>>The principal's office. I lean my head around the doorframe. She's at her desk, consulting a document on her screen. She looks up.
<</InformationUiPopUp>>
<<TalkNPC _npc "Ah. I wasn't expecting you.">>
<<TalkMC "I had something to tell you.">>
<<TalkNPC _npc "Come in, I'm listening.">>
<<InformationUiPopUp>>I close the door behind me and stay standing. She sets down her pen and looks at me, attentive. This is the final step to ensure she is completely submissive to me.
<</InformationUiPopUp>>
<<revealtext "chapter6">><<InformationUiPopUp "Psychic Power" #7aa2ff>>You decide to use your power on <<=_npc.name>>.<<if _npc.replaytalk == false>>
<em>-1 Psychic Power</em><</if>>
<</InformationUiPopUp>>
<<TalkMC "Listen to me.">>
<<InformationUiPopUp>>I lower my voice. She looks at me, her eyes in mine.
<</InformationUiPopUp>>
<<TalkMC "From now on I am your Master. You will do everything I want, for my pleasure alone, and you will love it. You will be totally and completely mine. And to mark that, you are going to prepare an evening at your place.">>
<<InformationUiPopUp>>After a few seconds her expression changes slowly, the professional rigidity dissolving, something else taking its place. She straightens slightly, then looks up at me differently.
<</InformationUiPopUp>>
<<TalkNPC _npc "...">>
<<TalkNPC _npc "I... yes. Yes, Master.">>
<<TalkNPC _npc "Can you give me a little time to prepare everything?">>
<<TalkMC "Take all the time you need.">>
<<TalkNPC _npc "Thank you, Master. I'll send you a message when everything is ready.">>
<<InformationUiPopUp>>I look at her for a moment, then head toward the door. She stays seated, hands resting on the desk, her expression different from anything it has been up until now, already thinking about how to prepare the upcoming evening.
<</InformationUiPopUp>>
<<InformationUiPopUp "⚠️ Important ⚠️" "#e65763">>This is not the end of chapter 6 for the Principal, she will contact you again by SMS later for the final scene.
<</InformationUiPopUp>><</revealtext>>
/* ====================================================
*
* -------------------------------- REPLAY CHAPTER --------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl > 5>><<set $SaveTalklvl = _npc.talklvl>><<set _npc.replaytalk = true>><<set _gotoReplayNpc = "Talk." + _npc.id>>
<<passagebg>><img src="assets/background.gif"/><</passagebg>>
<style>.rCard a{display:flex;align-items:center;gap:clamp(6px,1vw,10px);padding:clamp(8px,1.2vw,11px) clamp(10px,1.5vw,16px);border-radius:10px;background:rgba(230,87,99,.07);border:1px solid rgba(230,87,99,.18);text-decoration:none;transition:background .15s;}.rCard a:hover{background:rgba(230,87,99,.14);border-color:rgba(230,87,99,.35);}.rCard .rNum{font-size:calc(clamp(14px,1.8vw,18px) + var(--font-boost,0px));font-weight:950;color:rgba(255,255,255,.92);}.rCard .rLabel{font-size:calc(clamp(9px,1vw,12px) + var(--font-boost,0px));font-weight:900;letter-spacing:.16em;text-transform:uppercase;color:rgba(230,87,99,.55);}.rCard .rArrow{margin-left:auto;font-size:calc(clamp(9px,1vw,12px) + var(--font-boost,0px));font-weight:900;letter-spacing:.1em;color:rgba(230,87,99,.45);}</style><div style="display:flex;flex-direction:column;gap:6px;width:100%;margin-top:6px;"><div style="font-size:calc(clamp(9px,1vw,12px) + var(--font-boost,0px));font-weight:900;letter-spacing:.16em;text-transform:uppercase;color:rgba(255,255,255,.18);margin-bottom:6px;text-align:center;">- Select a scene to replay -</div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>01</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 0>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>02</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 1>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>03</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 2>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>04</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 3>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>05</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 4>><<goto _gotoReplayNpc>><</link>></div><<if $PrincipalChapter6End == true>><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>06</span><span class='rArrow'>REPLAY ›</span>">><<goto "Talk.Principal.Chapter6">><</link>></div><</if>></div>
<</if>><</if>><div class="BottomUiBarCustom">
<<if _npc.talklvl == 0>><<BottomButton "Decision">><<revealbtn "chapter1" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 1>><<BottomButton "Decision">><<revealbtn "chapter2" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 2>><<BottomButton "Decision">><<revealbtn "chapter3" "🧠 Use power" "" "powerid" "enterid" true>><<UsePsychicPower>><</revealbtn>><<revealbtn "wait" "⏳ Wait" "moveBtn" "enterid" "" false>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 3>><<BottomButton "Decision">><<revealbtn "chapter4" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 4>><<BottomButton "Decision">><<revealbtn "chapter5" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 5>><<BottomButton "Decision">><<revealbtn "chapter6" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><</if>>
<<BottomButton "Move" "moveBtn">><<if $FromOtherPlace == true>><<link "↩️ Return">><<if _npc.replaytalk == false>><<set _npc.talklvl++>><<set _npc.lvl++>><<set $PsychicPower -= 1>><<if _NextTime == true>><<set $Time++>><<set _NextTime = false>><</if>><<else>><<set _npc.talklvl = $SaveTalklvl>><<set _npc.replaytalk = false>><</if>><<ReturnToGoto>><<set $FromOtherPlace = false>><</link>><<else>><<link "↩️ Return">><<if _npc.replaytalk == false>><<set _npc.talklvl++>><<set _npc.lvl++>><<set $PsychicPower -= 1>><<if _NextTime == true>><<set $Time++>><<set _NextTime = false>><</if>><<else>><<set _npc.talklvl = $SaveTalklvl>><<set _npc.replaytalk = false>><</if>><<bgpause>><<goto _gotoNpc>><</link>><</if>><</BottomButton>>
</div><<sound "music" "music.music" true>><<set _raw = $ActiveNPC>><<if !_raw or _raw.id is undefined>>Invalid NPC.<<else>><<set _id = String(_raw.id)>><<set _key = "NPC" + _id>><<run State.temporary.npcObj = State.variables[State.temporary.key] || State.variables[_key]>><<set _npc = _npcObj>><<set _gotoNpc = _npc.id + ".interact">>
/* ====================================================
*
* ----------------------------------- CHAPTER 1 -----------------------------------------
*
*/ ====================================================
<<if _npc.talklvl == 0>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><</if>>
<<passagebg>><img src="assets/img/misc/???.png"/><</passagebg>>
<<InformationUiPopUp>>
<</InformationUiPopUp>>
<<TalkMC "">>
<<TalkNPC _npc "">>
/* ====================================================
*
* ----------------------------------- CHAPTER 2 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 1>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><</if>>
<<passagebg>><img src="assets/img/misc/???.png"/><</passagebg>>
<<InformationUiPopUp>>
<</InformationUiPopUp>>
<<TalkMC "">>
<<TalkNPC _npc "">>
/* ====================================================
*
* ----------------------------------- CHAPTER 3 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 2>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><</if>>
<<passagebg>><img src="assets/img/misc/???.png"/><</passagebg>>
<<InformationUiPopUp>>
<</InformationUiPopUp>>
<<TalkMC "">>
<<TalkNPC _npc "">>
/* ====================================================
*
* ----------------------------------- CHAPTER 4 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 3>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><</if>>
<<passagebg>><img src="assets/img/misc/???.png"/><</passagebg>>
<<InformationUiPopUp>>
<</InformationUiPopUp>>
<<TalkMC "">>
<<TalkNPC _npc "">>
/* ====================================================
*
* ----------------------------------- CHAPTER 5 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 4>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><</if>>
<<passagebg>><img src="assets/img/misc/???.png"/><</passagebg>>
<<InformationUiPopUp>>
<</InformationUiPopUp>>
<<TalkMC "">>
<<TalkNPC _npc "">>
/* ====================================================
*
* ----------------------------------- CHAPTER 6 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 5>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><</if>>
<<passagebg>><img src="assets/img/misc/???.png"/><</passagebg>>
<<InformationUiPopUp>>
<</InformationUiPopUp>>
<<TalkMC "">>
<<TalkNPC _npc "">>
/* ====================================================
*
* -------------------------------- REPLAY CHAPTER --------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl > 5>><<set $SaveTalklvl = _npc.talklvl>><<set _npc.replaytalk = true>><<set _gotoReplayNpc = "Talk." + _npc.id>>
<<passagebg>><img src="assets/background.gif"/><</passagebg>>
<style>.rCard a{display:flex;align-items:center;gap:clamp(6px,1vw,10px);padding:clamp(8px,1.2vw,11px) clamp(10px,1.5vw,16px);border-radius:10px;background:rgba(230,87,99,.07);border:1px solid rgba(230,87,99,.18);text-decoration:none;transition:background .15s;}.rCard a:hover{background:rgba(230,87,99,.14);border-color:rgba(230,87,99,.35);}.rCard .rNum{font-size:calc(clamp(14px,1.8vw,18px) + var(--font-boost,0px));font-weight:950;color:rgba(255,255,255,.92);}.rCard .rLabel{font-size:calc(clamp(9px,1vw,12px) + var(--font-boost,0px));font-weight:900;letter-spacing:.16em;text-transform:uppercase;color:rgba(230,87,99,.55);}.rCard .rArrow{margin-left:auto;font-size:calc(clamp(9px,1vw,12px) + var(--font-boost,0px));font-weight:900;letter-spacing:.1em;color:rgba(230,87,99,.45);}</style><div style="display:flex;flex-direction:column;gap:6px;width:100%;margin-top:6px;"><div style="font-size:calc(clamp(9px,1vw,12px) + var(--font-boost,0px));font-weight:900;letter-spacing:.16em;text-transform:uppercase;color:rgba(255,255,255,.18);margin-bottom:6px;text-align:center;">— Select a scene to replay —</div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>01</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 0>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>02</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 1>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>03</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 2>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>04</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 3>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>05</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 4>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>06</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 5>><<goto _gotoReplayNpc>><</link>></div></div>
<</if>><</if>><div class="BottomUiBarCustom">
<<if _npc.talklvl == 0>><<BottomButton "Decision">><<revealbtn "chapter1" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 1>><<BottomButton "Decision">><<revealbtn "chapter2" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 2>><<BottomButton "Decision">><<revealbtn "chapter3" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 3>><<BottomButton "Decision">><<revealbtn "chapter4" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 4>><<BottomButton "Decision">><<revealbtn "chapter5" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 5>><<BottomButton "Decision">><<revealbtn "chapter6" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><</if>>
<<BottomButton "Move" "moveBtn">><<if $FromOtherPlace == true>><<link "↩️ Return">><<if _npc.replaytalk == false>><<set _npc.talklvl++>><<set _npc.lvl++>><<set $PsychicPower -= 1>><<if _NextTime == true>><<set $Time++>><<set _NextTime = false>><</if>><<else>><<set _npc.talklvl = $SaveTalklvl>><<set _npc.replaytalk = false>><</if>><<ReturnToGoto>><<set $FromOtherPlace = false>><</link>><<else>><<link "↩️ Return">><<if _npc.replaytalk == false>><<set _npc.talklvl++>><<set _npc.lvl++>><<set $PsychicPower -= 1>><<if _NextTime == true>><<set $Time++>><<set _NextTime = false>><</if>><<else>><<set _npc.talklvl = $SaveTalklvl>><<set _npc.replaytalk = false>><</if>><<bgpause>><<goto _gotoNpc>><</link>><</if>><</BottomButton>>
</div><<sound "music" "music.music" true>><<set _raw = $ActiveNPC>><<if !_raw or _raw.id is undefined>>Invalid NPC.<<else>><<set _id = String(_raw.id)>><<set _key = "NPC" + _id>><<run State.temporary.npcObj = State.variables[State.temporary.key] || State.variables[_key]>><<set _npc = _npcObj>><<set _gotoNpc = _npc.id + ".interact">>
/* ====================================================
*
* ----------------------------------- CHAPTER 1 -----------------------------------------
*
*/ ====================================================
<<if _npc.talklvl == 0>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><</if>>
<<passagebg>><img src="assets/img/misc/???.png"/><</passagebg>>
<<InformationUiPopUp>>
<</InformationUiPopUp>>
<<TalkMC "">>
<<TalkNPC _npc "">>
/* ====================================================
*
* ----------------------------------- CHAPTER 2 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 1>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><</if>>
<<passagebg>><img src="assets/img/misc/???.png"/><</passagebg>>
<<InformationUiPopUp>>
<</InformationUiPopUp>>
<<TalkMC "">>
<<TalkNPC _npc "">>
/* ====================================================
*
* ----------------------------------- CHAPTER 3 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 2>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><</if>>
<<passagebg>><img src="assets/img/misc/???.png"/><</passagebg>>
<<InformationUiPopUp>>
<</InformationUiPopUp>>
<<TalkMC "">>
<<TalkNPC _npc "">>
/* ====================================================
*
* ----------------------------------- CHAPTER 4 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 3>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><</if>>
<<passagebg>><img src="assets/img/misc/???.png"/><</passagebg>>
<<InformationUiPopUp>>
<</InformationUiPopUp>>
<<TalkMC "">>
<<TalkNPC _npc "">>
/* ====================================================
*
* ----------------------------------- CHAPTER 5 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 4>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><</if>>
<<passagebg>><img src="assets/img/misc/???.png"/><</passagebg>>
<<InformationUiPopUp>>
<</InformationUiPopUp>>
<<TalkMC "">>
<<TalkNPC _npc "">>
/* ====================================================
*
* ----------------------------------- CHAPTER 6 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 5>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><</if>>
<<passagebg>><img src="assets/img/misc/???.png"/><</passagebg>>
<<InformationUiPopUp>>
<</InformationUiPopUp>>
<<TalkMC "">>
<<TalkNPC _npc "">>
/* ====================================================
*
* -------------------------------- REPLAY CHAPTER --------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl > 5>><<set $SaveTalklvl = _npc.talklvl>><<set _npc.replaytalk = true>><<set _gotoReplayNpc = "Talk." + _npc.id>>
<<passagebg>><img src="assets/background.gif"/><</passagebg>>
<style>.rCard a{display:flex;align-items:center;gap:clamp(6px,1vw,10px);padding:clamp(8px,1.2vw,11px) clamp(10px,1.5vw,16px);border-radius:10px;background:rgba(230,87,99,.07);border:1px solid rgba(230,87,99,.18);text-decoration:none;transition:background .15s;}.rCard a:hover{background:rgba(230,87,99,.14);border-color:rgba(230,87,99,.35);}.rCard .rNum{font-size:calc(clamp(14px,1.8vw,18px) + var(--font-boost,0px));font-weight:950;color:rgba(255,255,255,.92);}.rCard .rLabel{font-size:calc(clamp(9px,1vw,12px) + var(--font-boost,0px));font-weight:900;letter-spacing:.16em;text-transform:uppercase;color:rgba(230,87,99,.55);}.rCard .rArrow{margin-left:auto;font-size:calc(clamp(9px,1vw,12px) + var(--font-boost,0px));font-weight:900;letter-spacing:.1em;color:rgba(230,87,99,.45);}</style><div style="display:flex;flex-direction:column;gap:6px;width:100%;margin-top:6px;"><div style="font-size:calc(clamp(9px,1vw,12px) + var(--font-boost,0px));font-weight:900;letter-spacing:.16em;text-transform:uppercase;color:rgba(255,255,255,.18);margin-bottom:6px;text-align:center;">— Select a scene to replay —</div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>01</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 0>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>02</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 1>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>03</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 2>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>04</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 3>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>05</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 4>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>06</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 5>><<goto _gotoReplayNpc>><</link>></div></div>
<</if>><</if>><div class="BottomUiBarCustom">
<<if _npc.talklvl == 0>><<BottomButton "Decision">><<revealbtn "chapter1" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 1>><<BottomButton "Decision">><<revealbtn "chapter2" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 2>><<BottomButton "Decision">><<revealbtn "chapter3" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 3>><<BottomButton "Decision">><<revealbtn "chapter4" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 4>><<BottomButton "Decision">><<revealbtn "chapter5" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 5>><<BottomButton "Decision">><<revealbtn "chapter6" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><</if>>
<<BottomButton "Move" "moveBtn">><<if $FromOtherPlace == true>><<link "↩️ Return">><<if _npc.replaytalk == false>><<set _npc.talklvl++>><<set _npc.lvl++>><<set $PsychicPower -= 1>><<if _NextTime == true>><<set $Time++>><<set _NextTime = false>><</if>><<else>><<set _npc.talklvl = $SaveTalklvl>><<set _npc.replaytalk = false>><</if>><<ReturnToGoto>><<set $FromOtherPlace = false>><</link>><<else>><<link "↩️ Return">><<if _npc.replaytalk == false>><<set _npc.talklvl++>><<set _npc.lvl++>><<set $PsychicPower -= 1>><<if _NextTime == true>><<set $Time++>><<set _NextTime = false>><</if>><<else>><<set _npc.talklvl = $SaveTalklvl>><<set _npc.replaytalk = false>><</if>><<bgpause>><<goto _gotoNpc>><</link>><</if>><</BottomButton>>
</div><<sound "music" "music.music" true>><<set _raw = $ActiveNPC>><<if !_raw or _raw.id is undefined>>Invalid NPC.<<else>><<set _id = String(_raw.id)>><<set _key = "NPC" + _id>><<run State.temporary.npcObj = State.variables[State.temporary.key] || State.variables[_key]>><<set _npc = _npcObj>><<set _gotoNpc = _npc.id + ".interact">>
/* ====================================================
*
* ----------------------------------- CHAPTER 1 -----------------------------------------
*
*/ ====================================================
<<if _npc.talklvl == 0>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><</if>>
<<passagebg>><img src="assets/img/misc/???.png"/><</passagebg>>
<<InformationUiPopUp>>
<</InformationUiPopUp>>
<<TalkMC "">>
<<TalkNPC _npc "">>
/* ====================================================
*
* ----------------------------------- CHAPTER 2 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 1>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><</if>>
<<passagebg>><img src="assets/img/misc/???.png"/><</passagebg>>
<<InformationUiPopUp>>
<</InformationUiPopUp>>
<<TalkMC "">>
<<TalkNPC _npc "">>
/* ====================================================
*
* ----------------------------------- CHAPTER 3 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 2>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><</if>>
<<passagebg>><img src="assets/img/misc/???.png"/><</passagebg>>
<<InformationUiPopUp>>
<</InformationUiPopUp>>
<<TalkMC "">>
<<TalkNPC _npc "">>
/* ====================================================
*
* ----------------------------------- CHAPTER 4 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 3>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><</if>>
<<passagebg>><img src="assets/img/misc/???.png"/><</passagebg>>
<<InformationUiPopUp>>
<</InformationUiPopUp>>
<<TalkMC "">>
<<TalkNPC _npc "">>
/* ====================================================
*
* ----------------------------------- CHAPTER 5 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 4>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><</if>>
<<passagebg>><img src="assets/img/misc/???.png"/><</passagebg>>
<<InformationUiPopUp>>
<</InformationUiPopUp>>
<<TalkMC "">>
<<TalkNPC _npc "">>
/* ====================================================
*
* ----------------------------------- CHAPTER 6 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 5>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><</if>>
<<passagebg>><img src="assets/img/misc/???.png"/><</passagebg>>
<<InformationUiPopUp>>
<</InformationUiPopUp>>
<<TalkMC "">>
<<TalkNPC _npc "">>
/* ====================================================
*
* -------------------------------- REPLAY CHAPTER --------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl > 5>><<set $SaveTalklvl = _npc.talklvl>><<set _npc.replaytalk = true>><<set _gotoReplayNpc = "Talk." + _npc.id>>
<<passagebg>><img src="assets/background.gif"/><</passagebg>>
<style>.rCard a{display:flex;align-items:center;gap:clamp(6px,1vw,10px);padding:clamp(8px,1.2vw,11px) clamp(10px,1.5vw,16px);border-radius:10px;background:rgba(230,87,99,.07);border:1px solid rgba(230,87,99,.18);text-decoration:none;transition:background .15s;}.rCard a:hover{background:rgba(230,87,99,.14);border-color:rgba(230,87,99,.35);}.rCard .rNum{font-size:calc(clamp(14px,1.8vw,18px) + var(--font-boost,0px));font-weight:950;color:rgba(255,255,255,.92);}.rCard .rLabel{font-size:calc(clamp(9px,1vw,12px) + var(--font-boost,0px));font-weight:900;letter-spacing:.16em;text-transform:uppercase;color:rgba(230,87,99,.55);}.rCard .rArrow{margin-left:auto;font-size:calc(clamp(9px,1vw,12px) + var(--font-boost,0px));font-weight:900;letter-spacing:.1em;color:rgba(230,87,99,.45);}</style><div style="display:flex;flex-direction:column;gap:6px;width:100%;margin-top:6px;"><div style="font-size:calc(clamp(9px,1vw,12px) + var(--font-boost,0px));font-weight:900;letter-spacing:.16em;text-transform:uppercase;color:rgba(255,255,255,.18);margin-bottom:6px;text-align:center;">— Select a scene to replay —</div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>01</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 0>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>02</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 1>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>03</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 2>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>04</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 3>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>05</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 4>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>06</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 5>><<goto _gotoReplayNpc>><</link>></div></div>
<</if>><</if>><div class="BottomUiBarCustom">
<<if _npc.talklvl == 0>><<BottomButton "Decision">><<revealbtn "chapter1" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 1>><<BottomButton "Decision">><<revealbtn "chapter2" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 2>><<BottomButton "Decision">><<revealbtn "chapter3" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 3>><<BottomButton "Decision">><<revealbtn "chapter4" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 4>><<BottomButton "Decision">><<revealbtn "chapter5" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 5>><<BottomButton "Decision">><<revealbtn "chapter6" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><</if>>
<<BottomButton "Move" "moveBtn">><<if $FromOtherPlace == true>><<link "↩️ Return">><<if _npc.replaytalk == false>><<set _npc.talklvl++>><<set _npc.lvl++>><<set $PsychicPower -= 1>><<if _NextTime == true>><<set $Time++>><<set _NextTime = false>><</if>><<else>><<set _npc.talklvl = $SaveTalklvl>><<set _npc.replaytalk = false>><</if>><<ReturnToGoto>><<set $FromOtherPlace = false>><</link>><<else>><<link "↩️ Return">><<if _npc.replaytalk == false>><<set _npc.talklvl++>><<set _npc.lvl++>><<set $PsychicPower -= 1>><<if _NextTime == true>><<set $Time++>><<set _NextTime = false>><</if>><<else>><<set _npc.talklvl = $SaveTalklvl>><<set _npc.replaytalk = false>><</if>><<bgpause>><<goto _gotoNpc>><</link>><</if>><</BottomButton>>
</div><<sound "music" "music.music" true>><<set _raw = $ActiveNPC>><<if !_raw or _raw.id is undefined>>Invalid NPC.<<else>><<set _id = String(_raw.id)>><<set _key = "NPC" + _id>><<run State.temporary.npcObj = State.variables[State.temporary.key] || State.variables[_key]>><<set _npc = _npcObj>><<set _gotoNpc = _npc.id + ".interact">>
/* ====================================================
*
* ----------------------------------- CHAPTER 1 -----------------------------------------
*
*/ ====================================================
<<if _npc.talklvl == 0>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><</if>>
<<passagebg>><img src="assets/img/misc/???.png"/><</passagebg>>
<<InformationUiPopUp>>
<</InformationUiPopUp>>
<<TalkMC "">>
<<TalkNPC _npc "">>
/* ====================================================
*
* ----------------------------------- CHAPTER 2 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 1>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><</if>>
<<passagebg>><img src="assets/img/misc/???.png"/><</passagebg>>
<<InformationUiPopUp>>
<</InformationUiPopUp>>
<<TalkMC "">>
<<TalkNPC _npc "">>
/* ====================================================
*
* ----------------------------------- CHAPTER 3 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 2>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><</if>>
<<passagebg>><img src="assets/img/misc/???.png"/><</passagebg>>
<<InformationUiPopUp>>
<</InformationUiPopUp>>
<<TalkMC "">>
<<TalkNPC _npc "">>
/* ====================================================
*
* ----------------------------------- CHAPTER 4 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 3>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><</if>>
<<passagebg>><img src="assets/img/misc/???.png"/><</passagebg>>
<<InformationUiPopUp>>
<</InformationUiPopUp>>
<<TalkMC "">>
<<TalkNPC _npc "">>
/* ====================================================
*
* ----------------------------------- CHAPTER 5 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 4>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><</if>>
<<passagebg>><img src="assets/img/misc/???.png"/><</passagebg>>
<<InformationUiPopUp>>
<</InformationUiPopUp>>
<<TalkMC "">>
<<TalkNPC _npc "">>
/* ====================================================
*
* ----------------------------------- CHAPTER 6 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 5>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><</if>>
<<passagebg>><img src="assets/img/misc/???.png"/><</passagebg>>
<<InformationUiPopUp>>
<</InformationUiPopUp>>
<<TalkMC "">>
<<TalkNPC _npc "">>
/* ====================================================
*
* -------------------------------- REPLAY CHAPTER --------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl > 5>><<set $SaveTalklvl = _npc.talklvl>><<set _npc.replaytalk = true>><<set _gotoReplayNpc = "Talk." + _npc.id>>
<<passagebg>><img src="assets/background.gif"/><</passagebg>>
<style>.rCard a{display:flex;align-items:center;gap:clamp(6px,1vw,10px);padding:clamp(8px,1.2vw,11px) clamp(10px,1.5vw,16px);border-radius:10px;background:rgba(230,87,99,.07);border:1px solid rgba(230,87,99,.18);text-decoration:none;transition:background .15s;}.rCard a:hover{background:rgba(230,87,99,.14);border-color:rgba(230,87,99,.35);}.rCard .rNum{font-size:calc(clamp(14px,1.8vw,18px) + var(--font-boost,0px));font-weight:950;color:rgba(255,255,255,.92);}.rCard .rLabel{font-size:calc(clamp(9px,1vw,12px) + var(--font-boost,0px));font-weight:900;letter-spacing:.16em;text-transform:uppercase;color:rgba(230,87,99,.55);}.rCard .rArrow{margin-left:auto;font-size:calc(clamp(9px,1vw,12px) + var(--font-boost,0px));font-weight:900;letter-spacing:.1em;color:rgba(230,87,99,.45);}</style><div style="display:flex;flex-direction:column;gap:6px;width:100%;margin-top:6px;"><div style="font-size:calc(clamp(9px,1vw,12px) + var(--font-boost,0px));font-weight:900;letter-spacing:.16em;text-transform:uppercase;color:rgba(255,255,255,.18);margin-bottom:6px;text-align:center;">— Select a scene to replay —</div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>01</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 0>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>02</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 1>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>03</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 2>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>04</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 3>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>05</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 4>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>06</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 5>><<goto _gotoReplayNpc>><</link>></div></div>
<</if>><</if>><div class="BottomUiBarCustom">
<<if _npc.talklvl == 0>><<BottomButton "Decision">><<revealbtn "chapter1" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 1>><<BottomButton "Decision">><<revealbtn "chapter2" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 2>><<BottomButton "Decision">><<revealbtn "chapter3" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 3>><<BottomButton "Decision">><<revealbtn "chapter4" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 4>><<BottomButton "Decision">><<revealbtn "chapter5" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 5>><<BottomButton "Decision">><<revealbtn "chapter6" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><</if>>
<<BottomButton "Move" "moveBtn">><<if $FromOtherPlace == true>><<link "↩️ Return">><<if _npc.replaytalk == false>><<set _npc.talklvl++>><<set _npc.lvl++>><<set $PsychicPower -= 1>><<if _NextTime == true>><<set $Time++>><<set _NextTime = false>><</if>><<else>><<set _npc.talklvl = $SaveTalklvl>><<set _npc.replaytalk = false>><</if>><<ReturnToGoto>><<set $FromOtherPlace = false>><</link>><<else>><<link "↩️ Return">><<if _npc.replaytalk == false>><<set _npc.talklvl++>><<set _npc.lvl++>><<set $PsychicPower -= 1>><<if _NextTime == true>><<set $Time++>><<set _NextTime = false>><</if>><<else>><<set _npc.talklvl = $SaveTalklvl>><<set _npc.replaytalk = false>><</if>><<bgpause>><<goto _gotoNpc>><</link>><</if>><</BottomButton>>
</div><<sound "music" "music.music" true>><<set _raw = $ActiveNPC>><<if !_raw or _raw.id is undefined>>Invalid NPC.<<else>><<set _id = String(_raw.id)>><<set _key = "NPC" + _id>><<run State.temporary.npcObj = State.variables[State.temporary.key] || State.variables[_key]>><<set _npc = _npcObj>><<set _gotoNpc = _npc.id + ".interact">>
/* ====================================================
*
* ----------------------------------- CHAPTER 1 -----------------------------------------
*
*/ ====================================================
<<if _npc.talklvl == 0>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><</if>>
<<passagebg>><<sound "bg" "bg.empty" true>><img src="assets/img/misc/city/cityhall/mayoroffice.webp"/><</passagebg>>
<<InformationUiPopUp>>The hallway leading to the mayor's office is quiet, lined with framed photographs of city landmarks and past municipal events. A secretary sits at a desk just outside the office door, typing without looking up.
<</InformationUiPopUp>>
<<TalkRandom "City Hall Secretary" "assets/img/character/npc/g3.jpg" "Excuse me, do you have an appointment?">>
<<TalkMC "No. But I won't take long.">>
<<TalkRandom "City Hall Secretary" "assets/img/character/npc/g3.jpg" "I'm sorry, but <<print _npc.name>> is not available without a prior appointment, listen, you cannot just-">>
<<InformationUiPopUp>>I walk into the office without paying much more attention to the secretary. The office is large, formal, and impeccably organized. Wide windows overlook the city square. <<print _npc.name>> is sitting behind her desk, phone pressed to her ear, one hand raised, her voice clipped and barely controlled.
<</InformationUiPopUp>>
<<TalkNPC _npc "No! That is not what I approved! The budget report was supposed to be on my desk today. We are several days behind. Yes, today! I am fully aware of what day it is, that is precisely why I am calling you.">>
<video src="assets/img/story/character/mayor/0/01.mp4"/>
<<TalkNPC _npc "I do not care about the printing delays. That is not my problem to solve. Have it corrected and send it over before end of day or I will have someone else handle the file entirely. Are we clear? Good.">>
<<InformationUiPopUp>>She hangs up and looks at me directly. Whatever patience she had left is already spent.
<</InformationUiPopUp>>
<<TalkNPC _npc "You walked past my secretary.">>
<<TalkMC "She was mid-sentence. I did not want to interrupt her.">>
<<TalkNPC _npc "I have a council meeting in a few minutes and three calls I have not returned yet. Whoever you are, this is not the right day, and this is certainly not the right way to get a meeting.">>
<<TalkMC "I know, I will be quick.">>
<<InformationUiPopUp>>I sit down in the chair across from her desk without being invited to.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mayor/0/02.mp4"/>
<<TalkNPC _npc "I did not ask you to sit.">>
<<TalkMC "My name is <<print $MCPlayer.firstname>>. I heard about the Financial District infrastructure proposal and I think there is a structural flaw in how the timeline is being presented to the council.">>
<<TalkNPC _npc "And you are, exactly? A consultant? A journalist?">>
<<TalkMC "Neither. Just someone who noticed something the engineers probably glossed over because it makes the schedule look worse than it is.">>
<<TalkNPC _npc "The Financial District proposal was signed off by three separate engineering firms and reviewed by my infrastructure team. I highly doubt a man who walked past my secretary without an appointment has found something they missed.">>
<<TalkMC "The phase two drainage assessment references soil composition data from 2009. There was significant ground displacement in that district in 2017, documented in a municipal geological survey. Nobody updated the baseline. The timeline is built on outdated foundation assumptions.">>
<<TalkNPC _npc "That survey is not part of the infrastructure documentation package.">>
<<TalkMC "No. Different department. Easy to miss if you are not specifically looking for it.">>
<<InformationUiPopUp>>She holds my gaze for a moment. Something shifted in her attention, barely visible, but there. She sets down her pen.
<</InformationUiPopUp>>
<<TalkNPC _npc "Where exactly did you come across this information?">>
<<TalkMC "Does it matter? The information is what it is.">>
<<TalkNPC _npc "It matters quite a lot when a stranger walks into my office with details that are not publicly available and offers them for no apparent reason.">>
<<TalkMC "I am not offering them for no reason. I am telling you something useful because I think you should know before your meeting. That is all.">>
<<TalkNPC _npc "People do not walk into a mayor's office uninvited out of civic duty. So I will ask again. What do you want?">>
<<TalkMC "Nothing. If you do not believe me, bring it up at the meeting. You will see for yourself that I was right.">>
<<InformationUiPopUp>>She studies me. The skepticism is still there, but so is the calculation. She is thinking about the meeting, about what it would mean if this turned out to be accurate, and about what it would mean if she let me walk out without knowing the rest.
<</InformationUiPopUp>>
<<TalkNPC _npc "You said it was documented. I want the reference. The full reference.">>
<<TalkMC "Go to the meeting. See what happens. If you want to talk after, I will give you my number so you know how to reach me.">>
<<TalkNPC _npc "That is not how this works. You came to me. You do not get to leave with half an answer.">>
<<InformationUiPopUp>>She is not going to let this go. And I can see it, she is engaged. I could walk out and wait. Or I could make sure she stops asking questions and starts trusting.
<</InformationUiPopUp>>
<<revealtext "chapter1">><<InformationUiPopUp "Psychic Power" #7aa2ff>>You decide to use your power on <<=_npc.name>>.
<em>-1 Psychic Power</em><</InformationUiPopUp>>
<<TalkMC "Listen to me.">>
<<InformationUiPopUp>>I hold her gaze and lower my voice just slightly.
<</InformationUiPopUp>>
<<TalkMC "I am here to help you, nothing more. You do not need to know where the information comes from. You do not need to push for more than what I have already told you. What you need is to trust that I am on your side, and that once your meeting is over, you will want to hear more of what I have to say.">>
<<TalkNPC _npc "...">>
<<InformationUiPopUp>>A few seconds pass. The sharpness in her expression softens, not into warmth exactly, but into something quieter.
<</InformationUiPopUp>>
<<TalkNPC _npc "I... yes. You are right. I do not need to complicate this.">>
<<TalkNPC _npc "You said you wanted to help me.">>
<<TalkMC "That is all.">>
<<TalkNPC _npc "Then I will take what you gave me and see where it leads. Do you have a way for me to reach you?">>
<<TalkMC "Of course, here is my number. Call me after your meeting if you want more information.">>
<<InformationUiPopUp>>I stand up and head for the door. Behind me, I hear her pick up the phone again, quieter this time. She is already thinking about the meeting.
<</InformationUiPopUp>><</revealtext>>
/* ====================================================
*
* ----------------------------------- CHAPTER 2 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 1>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><</if>>
<<passagebg>><<sound "bg" "bg.empty" true>><img src="assets/img/misc/city/cityhall/mayoroffice.webp"/><</passagebg>>
<<InformationUiPopUp>>The office is the same as before, formal and organized. <<print _npc.name>> is sitting at her desk, working through a pile of files. She looks up the moment I walk in, which tells me she was expecting me.
<</InformationUiPopUp>>
<<TalkNPC _npc "There you are, go ahead and sit down.">>
<<TalkMC "You said in your message that you had questions.">>
<<TalkNPC _npc "Questions, and something else. What you told me before the meeting was accurate. The phase two timeline did have a flaw. My team confirmed it and we were able to correct course before it became a problem in front of the council.">>
<<TalkMC "Good.">>
<<TalkNPC _npc "It saved me from an embarrassing situation. So thank you. But-">>
<<TalkMC "Don't mention it. But?">>
<<TalkNPC _npc "But now, how did you know? You're not an engineer or a consultant. So where did that information come from?">>
<<TalkMC "I pay attention. Most people don't.">>
<<TalkNPC _npc "That's not an answer.">>
<<TalkMC "It's the only one I have. I read, I listen, I notice when something doesn't add up. That kind of inconsistency exists in a lot of places. You just have to know where to look.">>
<video src="assets/img/story/character/mayor/1/01.mp4"/>
<<TalkNPC _npc "I can see you're not going to give me anything. And I assume you didn't come back just to hear me say thank you.">>
<<TalkMC "No.">>
<<TalkNPC _npc "Then tell me what you want.">>
<<TalkMC "Not yet. You have other problems coming.">>
<<TalkNPC _npc "What do you mean?">>
<<TalkMC "The financial district zoning revision is going to face opposition from the Hargrove Group at the next session. They have direct interests in that site and they won't let it go without pushing back. If you walk in without anticipating their argument, you risk losing the vote.">>
<<TalkNPC _npc "Hargrove, yes. Their opposition doesn't surprise me. But what makes you think I'm not prepared?">>
<<TalkMC "Request the traffic impact annex from the urban planning office before the session. It contains figures that directly contradict their main argument. They won't expect you to have it.">>
<<TalkNPC _npc "And the other problems you mentioned?">>
<<TalkMC "We'll get to those. But nothing I give you is free.">>
<<InformationUiPopUp>>A brief silence. She holds my gaze without flinching.
<</InformationUiPopUp>>
<<TalkNPC _npc "I suspected as much. I want to be clear about what you expect. A contract? A recommendation? Because if we're working together, I want to know exactly what I'm agreeing to.">>
<<TalkMC "It's not that simple.">>
<<TalkNPC _npc "It always is. People always want something specific. So what is it?">>
<<TalkMC "Something personal.">>
<<TalkNPC _npc "That's vague...">>
<<TalkMC "Intentionally.">>
<<InformationUiPopUp>>She crosses her arms. I can see she wants to define a framework, something clear and controllable. But a precise framework is also something she can use against me. I'd rather she accept something she can't quite name.
<</InformationUiPopUp>>
<<revealtext "chapter2">><<InformationUiPopUp "Psychic Power" #7aa2ff>>You decide to use your power on <<=_npc.name>>.
<em>-1 Psychic Power</em><</InformationUiPopUp>>
<<TalkMC "Listen to me.">>
<<InformationUiPopUp>>I lower my voice slightly, holding her gaze.
<</InformationUiPopUp>>
<<TalkMC "You don't need everything defined right now. What you know is that I'm useful, and that you can trust me. And to show me that you understand that, you're going to do something simple. Something personal, as you put it.">>
<<TalkNPC _npc "...">>
<<InformationUiPopUp>>A few seconds. The tension in her shoulders eases. She looks at me differently, as if the question she was about to ask has lost its importance. Then, without a word, she reaches for the collar of her shirt and slowly undoes the first two buttons, without making an event of it, the way someone signs a document. She sets her hands back on the desk.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mayor/1/02.mp4"/>
<<TalkNPC _npc "I've spent six years building this term. I intend to be re-elected. If you can help me do that, I'm prepared to be very cooperative.">>
<<TalkMC "I can see that.">>
<video src="assets/img/story/character/mayor/1/03.mp4"/>
<<TalkNPC _npc "The traffic impact annex. Anything else I should know before the session?">>
<<TalkMC "Make sure it includes pedestrian flow projections, not just vehicle data. That's what they'll try to pick apart.">>
<video src="assets/img/story/character/mayor/1/04.mp4"/>
<<TalkNPC _npc "Noted.">>
<<TalkNPC _npc "You'll come back?">>
<<TalkMC "When you need me.">>
<<TalkNPC _npc "And if I need you before that?">>
<<TalkMC "You have my number.">>
<<InformationUiPopUp>>She turns back to her files. The conversation is over, and we both know exactly what it was, even if she couldn't quite put it into words. That's exactly how I wanted it.
<</InformationUiPopUp>><</revealtext>>
/* ====================================================
*
* ----------------------------------- CHAPTER 3 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 2>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><</if>>
<<passagebg>><<sound "bg" "bg.empty" true>><img src="assets/img/misc/city/cityhall/mayoroffice.webp"/><</passagebg>>
<<InformationUiPopUp>>I arrive at her office. She already has her eyes on the door when I walk in, and something in her expression has changed compared to before. Less control, less tension. She clearly needs something.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mayor/2/01.mp4"/>
<<TalkNPC _npc "Close the door.">>
<<TalkMC "You said it was urgent.">>
<<TalkNPC _npc "It's Hargrove. Since the zoning vote, they've started talking to the media. Two articles this week questioning my decisions on the financial district. They're trying to weaken me publicly.">>
<<TalkMC "That was predictable.">>
<<TalkNPC _npc "Predictable doesn't mean manageable. And that's not all... I received a permit modification request from them yesterday, they want to change certain technical parameters of the project. The request is worded very vaguely, my team can't figure out exactly what they're trying to change.">>
<<InformationUiPopUp>>I understand immediately. They're trying to quietly correct the geological problem in the official documents without anyone noticing what they're really doing.
<</InformationUiPopUp>>
<<TalkMC "Don't approve that request.">>
<<TalkNPC _npc "Why?">>
<<TalkMC "Because when a technical modification is worded vaguely, it's rarely an accident. Request a full technical review before going any further. It slows the process down without tipping them off directly.">>
<<TalkNPC _npc "And the articles?">>
<<TalkMC "Ignore them for now. Responding right away just gives them visibility. What you need is a clean file on the financial district, something solid you can put on the table at the right moment. Not a defensive response to every attack.">>
<<TalkNPC _npc "And that solid file, can you help me build it?">>
<<TalkMC "That's why you called me, isn't it?">>
<<InformationUiPopUp>>A silence. She looks at me in a way I'm starting to recognize. The pressure she's been building up over the past few days is looking for a way out, and I'm the only person in this room she can direct it toward.
<</InformationUiPopUp>>
<<TalkNPC _npc "You're right about the technical review, I'm going to block the request tonight.">>
<<TalkMC "Good.">>
<<TalkNPC _npc "And going forward? There will inevitably be more attacks.">>
<<TalkMC "There will be. But like I said, when they attack, don't respond. They'll reveal something about what they're trying to protect. Let them talk. We'll see what surfaces.">>
<<InformationUiPopUp>>She nods slowly. Then she sets her pen down and looks at me differently.
<</InformationUiPopUp>>
<<TalkNPC _npc "I don't know how you do that.">>
<<TalkMC "Do what?">>
<<TalkNPC _npc "See what's happening so clearly. I have an entire team and nobody has told me half of what you've told me in three meetings.">>
<<InformationUiPopUp>>This is the moment. She's engaged, dependent, and she's starting to feel it without quite being able to name it. I could let it settle naturally, but nothing would guarantee it holds. Or I could make sure it becomes something deeper, something she won't be able to ignore.
<</InformationUiPopUp>>
<<revealtext "chapter3">><<InformationUiPopUp "Psychic Power" #7aa2ff>>You decide to use your power on <<=_npc.name>>.
<em>-1 Psychic Power</em><</InformationUiPopUp>>
<<TalkMC "Listen to me.">>
<<InformationUiPopUp>>She holds my gaze without moving.
<</InformationUiPopUp>>
<<TalkMC "You need me, and you know it. And to show me that you understand that, you're going to get up, come over to me, and jerk me off. Not because I'm asking you to, but because that's the way you've chosen to unwind and to thank me.">>
<<TalkNPC _npc "...">>
<<InformationUiPopUp>>A few seconds. Her expression shifts imperceptibly. Something eases, not her posture, not her composure, but something underneath.
<</InformationUiPopUp>>
<<TalkNPC _npc "Yes, it's... yes.">>
<<InformationUiPopUp>>She stands, turns her back to me, and slowly slides her skirt down to the floor. Then she leans forward over the desk, palms flat on the surface, letting me see her ass framed by her lace thong.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mayor/2/02.mp4"/>
<<InformationUiPopUp>>She stays in that position, bent over the desk, and picks the conversation back up as if nothing has changed, pen in hand, slowly swaying her ass in front of me while she talks.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mayor/2/03.mp4"/>
<<TalkNPC _npc "The technical review. I'll block it tonight and request a full report by end of the week.">>
<<TalkMC "That's right.">>
<<TalkNPC _npc "And the articles, I wait.">>
<<TalkMC "That's right too, you wait.">>
<<InformationUiPopUp>>She straightens, turns around, and sits on the edge of the desk facing me. She unbuttons her shirt slowly without taking it off, letting her bra show, then sets her hands on her skin and touches herself while she keeps talking, eyes on mine.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mayor/2/04.mp4"/>
<<TalkNPC _npc "If they file a second modification request?">>
<<TalkMC "You contact me before responding.">>
<<TalkNPC _npc "Alright, works for me.">>
<<InformationUiPopUp>>She slides off the desk, pushes me back into her chair and kneels in front of me. She pulls my cock out through the zipper and takes it in her hand, starting to jerk me off slowly, eyes lifted toward me from time to time.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mayor/2/05.mp4"/>
<<InformationUiPopUp>>When it's done, she gets up, buttons her shirt back up, straightens her skirt, and goes back to her seat, picks up her pen, same posture as when I arrived.
<</InformationUiPopUp>>
<<TalkNPC _npc "I'll send you a message as soon as I have the technical report.">>
<<TalkMC "Good, sounds good.">>
<<InformationUiPopUp>>She's already writing by the time I reach the door.
<</InformationUiPopUp>><</revealtext>>
/* ====================================================
*
* ----------------------------------- CHAPTER 4 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 3>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<if $Inventory.archivefile and $Inventory.archivefile.qty >= 1>><<run delete State.variables.Inventory.archivefile>><</if>><</if>>
<<passagebg>><<sound "bg" "bg.empty" true>><img src="assets/img/misc/city/cityhall/mayoroffice.webp"/><</passagebg>>
<<InformationUiPopUp>>I walk into her office, she looks up at me, and I can tell from her expression that she's tense.
<</InformationUiPopUp>>
<<TalkNPC _npc "I didn't call for you.">>
<<TalkMC "I know, but what I have to tell you couldn't wait.">>
<<TalkNPC _npc "I have a press conference in two hours and three urgent files on my desk, so please make it quick.">>
<<TalkMC "Hargrove. The construction project needs to be stopped.">>
<<InformationUiPopUp>>She stops and looks at me again.
<</InformationUiPopUp>>
<<TalkNPC _npc "I beg your pardon?">>
<<TalkMC "The Hargrove construction project in the financial district. It needs to be blocked.">>
<<TalkNPC _npc "You're asking me to stop a major construction project, validated by the city, right in the middle of a media offensive by Hargrove against me. Do you realize what you're asking?">>
<<TalkMC "I know it looks suicidal from the outside, but I have my reasons.">>
<<TalkNPC _npc "Up until now you've given me useful information, angles I didn't have. But what you're asking now is something completely different. I can't block a project of this scale without documented grounds, it would destroy me politically.">>
<<TalkMC "I have the documented grounds.">>
<<InformationUiPopUp>>I set the GE-2017-114 file on her desk. She looks at it, looks at me, then picks it up.
<</InformationUiPopUp>>
<<TalkMC "Go ahead, read it.">>
<<InformationUiPopUp>>She starts reading. I let her. She turns the pages slowly at first, then faster, then stops on one section and reads it again. When she looks up, her expression has completely changed.
<</InformationUiPopUp>>
<<TalkNPC _npc "This survey dates from 2017, but the project was approved in 2019. If this document existed in the municipal archives...">>
<<TalkMC "Nobody came across it because it was filed under the wrong department. But it exists, and it proves they're building on geologically compromised ground without having declared it.">>
<<InformationUiPopUp>>She sets the file back down on the desk slowly. I can see she understands the full extent of what this implies, not just for Hargrove, but for her, and what she can do with it.
<</InformationUiPopUp>>
<<TalkNPC _npc "And you want me to act on this now?">>
<<TalkMC "Exactly, now.">>
<<TalkNPC _npc "Listen to me carefully. I can't pick up the phone and shut down a project of this scale just because a man who has never told me his name drops a file on my desk, even if you've helped me. There are still too many grey areas around you and that's not how I operate.">>
<<InformationUiPopUp>>She stands up, moving to end the conversation. I know what I have left to do.
<</InformationUiPopUp>>
<<revealtext "chapter4">><<InformationUiPopUp "Psychic Power" #7aa2ff>>You decide to use your power on <<=_npc.name>>.
<em>-1 Psychic Power</em><</InformationUiPopUp>>
<<TalkMC "Listen to me.">>
<<InformationUiPopUp>>I lower my voice. She goes still.
<</InformationUiPopUp>>
<<TalkMC "You're going to do what I'm asking. You're going to make that call, block the project, and you're going to do it now. Because you know it's the right decision, and because you trust me completely to guide you this far. And then you're going to thank me for helping you, like the last times.">>
<<TalkNPC _npc "...">>
<<InformationUiPopUp>>For a few seconds she doesn't move, then her expression shifts, the resistance dissolving, replaced by something calmer.
<</InformationUiPopUp>>
<<TalkNPC _npc "You're right.">>
<<InformationUiPopUp>>She picks the file back up, goes through it one last time, then sets it aside. Then, without transition, she removes her skirt and starts unbuttoning her shirt.
<</InformationUiPopUp>>
<<InformationUiPopUp>>She removes her shirt, now in her underwear, sitting on the edge of her desk, the file beside her.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mayor/3/01.mp4"/>
<<InformationUiPopUp>>Her other hand slides slowly down between her legs, fingers pressing through the fabric of her underwear, her eyes on mine, while we discuss what needs to happen next.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mayor/3/02.mp4"/>
<<TalkNPC _npc "Should I make the call now?">>
<<TalkMC "Go ahead.">>
<<InformationUiPopUp>>She pulls her bra down to expose her bare chest, then dials the number. Her voice comes out exactly as it always does when the line picks up.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mayor/3/03.mp4"/>
<<TalkNPC _npc "Hello, this is <<print _npc.name>>. I want an immediate suspension of works on the Hargrove site in the financial district. Grounds: documented geological anomaly not declared at the time of the permit application. I'll be sending the reference file within the hour.">>
<<TalkNPC _npc "Yes.">>
<<TalkNPC _npc "No, it cannot wait. Do what needs to be done and keep me informed.">>
<<InformationUiPopUp>>Her hand didn't stop during the call. Her breathing stayed steady. Then she hangs up.
<</InformationUiPopUp>>
<<InformationUiPopUp>>Call finished, she stays seated on the desk, one hand still inside her underwear, the other moving slowly up to her chest. She looks at me.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mayor/3/04.mp4"/>
<<InformationUiPopUp>>I sit down in the chair across from her. She slides off the desk and kneels in front of me, pulls my cock out through the zipper, and takes me in her mouth, with the same deliberate calm she brought to everything before.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mayor/3/05.mp4"/>
<<TalkNPC _npc "<em>Mmh... glrk... mmh...</em>">>
<<TalkMC "Take your time.">>
<<InformationUiPopUp>>She keeps going, without stopping, until I finish coming in her mouth. She swallows everything while continuing to suck me gently all the way through.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mayor/3/06.mp4"/>
<<InformationUiPopUp>>She gets up, picks up her shirt and skirt, and starts getting dressed, still with the same composure.
<</InformationUiPopUp>>
<<TalkNPC _npc "The site will be suspended by tonight. The legal implications for Hargrove will take a few weeks to materialize.">>
<<TalkMC "Perfect.">>
<<TalkNPC _npc "And the land?">>
<<TalkMC "When it comes back to the city, I want to be in a position to benefit from it.">>
<<TalkNPC _npc "I'll remember that.">>
<<InformationUiPopUp>>Conversation over, she turns back to her desk and picks up her pen. Hargrove doesn't know it yet, but it's over for them.
<</InformationUiPopUp>><</revealtext>>
/* ====================================================
*
* ----------------------------------- CHAPTER 5 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 4>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<if $Inventory.acquisitiondocument and $Inventory.acquisitiondocument.qty >= 1>><<run delete State.variables.Inventory.acquisitiondocument>><</if>><</if>>
<<passagebg>><<sound "bg" "bg.empty" true>><img src="assets/img/misc/city/cityhall/mayoroffice.webp"/><</passagebg>>
<<InformationUiPopUp>>I arrive at her office, something in her expression tells me she was expecting my visit.
<</InformationUiPopUp>>
<<TalkNPC _npc "The financing?">>
<<TalkMC "Confirmed, thirty million, the transfer went through.">>
<<TalkNPC _npc "Good. Then we can move forward on the documents on our end.">>
<<InformationUiPopUp>>She opens a file on her desk and pulls out several pages.
<</InformationUiPopUp>>
<<TalkNPC _npc "The city's financial assistance is set at two million dollars under the urban development program. That's the maximum I can allocate on this type of file without triggering a full budget review.">>
<<TalkMC "Two million? That's nowhere near enough.">>
<<TalkNPC _npc "That's the regulatory framework.">>
<<TalkMC "You fast-tracked this file, you blocked Hargrove, you stalled to give me time to get into position. Two million isn't proportional to what you put in place.">>
<<TalkNPC _npc "I understand your point, but I can't go beyond that without exposing the city to an audit. It would put my term at risk.">>
<<TalkMC "Given everything we've built together, you can find a way.">>
<<TalkNPC _npc "No. Not on this point. I'm sorry, but my answer is no.">>
<<InformationUiPopUp>>She closes the file, signaling that the discussion is over. I can see she won't move through normal channels.
<</InformationUiPopUp>>
<<revealtext "chapter5">><<InformationUiPopUp "Psychic Power" #7aa2ff>>You decide to use your power on <<=_npc.name>>.
<em>-1 Psychic Power</em><</InformationUiPopUp>>
<<TalkMC "Listen to me.">>
<<TalkMC "You're going to revise the financial assistance amount upward. You'll find the regulatory framework to justify it because you know this project deserves that support. And to celebrate, we're going to fuck, right here, right now, before signing anything.">>
<<TalkNPC _npc "...">>
<<InformationUiPopUp>>She reopens the file, rereads something, and sets down her pen.
<</InformationUiPopUp>>
<<TalkNPC _npc "There is actually an exceptional development fund I hadn't mentioned. I can mobilize it. The total amount of the assistance would be more substantial.">>
<<TalkMC "That's better.">>
<<InformationUiPopUp>>She stands up, removes her jacket, then her skirt. She pulls the front of her bra down to free her tits and sits on the edge of the desk facing me.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mayor/4/01.mp4"/>
<<InformationUiPopUp>>I move toward her. I raise my hands, taking her tits in both hands.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mayor/4/02.mp4"/>
<<TalkNPC _npc "<em>Ah... mmh...</em>">>
<<InformationUiPopUp>>She stands up, turns her back to me, and slowly pulls her underwear down in front of me, then spreads her legs, back arched. I crouch down right behind her to take in the view.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mayor/4/03.mp4"/>
<<InformationUiPopUp>>She stays in that position, legs spread, back arched, and slides a hand between her legs, rubbing her pussy while looking back at me over her shoulder.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mayor/4/04.mp4"/>
<<TalkNPC _npc "<em>Ah... mmh... yes...</em>">>
<<InformationUiPopUp>>I lie down on the floor, pulling my cock out through the zipper. She sits down on me, facing away, sinking slowly onto my cock.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mayor/4/05.mp4"/>
<<TalkNPC _npc "<em>Ah... fuck... it's so deep...</em>">>
<<TalkMC "Keep going.">>
<video src="assets/img/story/character/mayor/4/06.mp4"/>
<<TalkNPC _npc "<em>Ah... ah... yes...</em>">>
<<InformationUiPopUp>>Then I decide to set my own rhythm, picking up the pace.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mayor/4/07.mp4"/>
<<TalkNPC _npc "<em>Ah... mmh... fuck...</em>">>
<<InformationUiPopUp>>She turns around without pulling off, now facing me, legs wide open, feet flat on either side of my hips, picking the movement back up.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mayor/4/08.mp4"/>
<<TalkNPC _npc "<em>Ah... yes... like that...</em>">>
<<TalkMC "Keep going like that, it's perfect.">>
<video src="assets/img/story/character/mayor/4/09.mp4"/>
<<InformationUiPopUp>>Her hand slides down between her legs, rubbing her pussy while she keeps moving on top of me.
<</InformationUiPopUp>>
<<TalkNPC _npc "<em>Ah... ah... yes... yes...</em>">>
<<InformationUiPopUp>>We get up from the floor and she leans forward over the desk, her upper body flat against the surface. I position myself behind her and push into her.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mayor/4/10.mp4"/>
<<TalkNPC _npc "<em>Ah... fuck... more...</em>">>
<video src="assets/img/story/character/mayor/4/11.mp4"/>
<<TalkNPC _npc "<em>Ah... ah... yes... yes...</em>">>
<<TalkNPC _npc "Fuck it feels so good...">>
<<InformationUiPopUp>>Her hand slides under her, rubbing her pussy while I keep fucking her.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mayor/4/12.mp4"/>
<<TalkNPC _npc "<em>Ah... mmh... I'm going to...</em>">>
<<TalkMC "It's not time to come yet.">>
<<TalkNPC _npc "Yes... okay...">>
<<InformationUiPopUp>>I turn her around and lift her onto the edge of the desk, legs spread wide. I position myself between them and push into her again.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mayor/4/13.mp4"/>
<<TalkNPC _npc "<em>Ah... yes... like that...</em>">>
<<TalkNPC _npc "Please... please don't stop.">>
<video src="assets/img/story/character/mayor/4/14.mp4"/>
<<TalkNPC _npc "<em>Ah... ah... fuck... yes...</em>">>
<<InformationUiPopUp>>I pick up the pace even more, until I end up coming inside her, without stopping. She stays with her eyes half-closed, catching her breath slowly.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mayor/4/15.mp4"/>
<<TalkNPC _npc "<em>Ah... mmh...</em>">>
<<InformationUiPopUp>>A few seconds pass. She straightens up, puts herself back together, bra, skirt, jacket. Then she picks the file back up from the desk as if nothing happened, pen in hand.
<</InformationUiPopUp>>
<<TalkNPC _npc "Shall we sign?">>
<<TalkMC "Let's do it.">>
<<InformationUiPopUp>>We spend the next fifteen minutes going through and signing the documents one by one. She stamps, countersigns, files. Once done, she hands me my copy.
<</InformationUiPopUp>>
<<TalkNPC _npc "The site can resume tomorrow morning. The financial assistance will be transferred within five business days.">>
<<TalkMC "Perfect.">>
<<InformationUiPopUp>>She picks up her pen and goes back to her notes. I walk out of the office with the documents under my arm. The site can start back up tomorrow.
<</InformationUiPopUp>><</revealtext>>
/* ====================================================
*
* ----------------------------------- CHAPTER 6 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 5>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><</if>>
<<passagebg>><<sound "bg" "bg.empty" true>><img src="assets/img/misc/city/cityhall/mayoroffice.webp"/><</passagebg>><<InformationUiPopUp>>Her office. She called me in for an administrative update on the construction site. She's behind her desk, professional as always, the file open in front of her. We've been talking for a few minutes about deadlines and forms. Then I stop listening. I look at her. And I decide that tonight, I want to go much further with her.
<</InformationUiPopUp>>
<<revealtext "chapter6">><<InformationUiPopUp "Psychic Power" #7aa2ff>>You decide to use your power on <<=_npc.name>>.
<em>-1 Psychic Power</em><</InformationUiPopUp>>
<<TalkMC "Listen to me.">>
<<TalkMC "Tonight you're going to invite me to your place. You want to belong to me completely, without limits. You will call me Master from now on, and you will do everything I ask with pleasure.">>
<<TalkNPC _npc "...">>
<<InformationUiPopUp>>She sets her pen down. Then looks me in the eyes.
<</InformationUiPopUp>>
<<TalkNPC _npc "I want you to come to my place. Now. I want to belong to you, Master. Completely.">>
<<TalkMC "Then let's go.">><</revealtext>>
<<revealtext "enter">><<passagebg>><<sound "bg" "bg.empty" true>><img src="assets/img/misc/neighborhood/mayor/home.webp"/><</passagebg>><<InformationUiPopUp>>Her place. The living room is dim. Red cups still scattered across the coffee table, a ping pong ball sitting in one of them, a half-empty bottle pushed to the corner. She sits down among it all without tidying anything, hands in her lap, back straight out of habit. I take the armchair across from her.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mayor/5/01.mp4"/>
<<TalkNPC _npc "I have never said this out loud to anyone.">>
<<TalkMC "Said what?">>
<<TalkNPC _npc "That I want to belong to someone, have no decisions to make, just let myself go, be given orders. Now, when I'm with you, I only want to be your slut.">>
<<TalkMC "And how long have you been thinking about this?">>
<<TalkNPC _npc "It started at the office. The way you just tell me what to do, and I do it without thinking twice. Then at some point I realized I loved that feeling of having no control.">>
<<TalkMC "So now you want to go further.">>
<<TalkNPC _npc "Yes. I want there to be no limit. I want to see what it feels like to just... be a good little bitch.">>
<<InformationUiPopUp>>I stand from the armchair and come sit beside her on the couch.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mayor/5/02.mp4"/>
<<TalkNPC _npc "Is that something you want? Or am I asking for something that doesn't interest you?">>
<<TalkMC "It interests me. A lot.">>
<<TalkNPC _npc "Thank you Master. Tell me what to do. I'll do it right away.">>
<<TalkMC "Then we start now. Stand up.">>
<<TalkNPC _npc "Yes, Master.">>
<video src="assets/img/story/character/mayor/5/03.mp4"/>
<<TalkMC "Turn slowly.">>
<<TalkNPC _npc "Like this?">>
<<TalkMC "Slower.">>
<<TalkNPC _npc "Yes, Master.">>
<<TalkMC "Lift your dress, I want to see what's underneath.">>
<<InformationUiPopUp>>She grabs the hem of her dress and pulls it up to her waist. Nothing underneath, completely bare from the hips down under her dress, as if she had planned for exactly this.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mayor/5/04.mp4"/>
<<TalkMC "You're a real little slut, no underwear.">>
<<TalkNPC _npc "It's recent, I love that feeling of freedom, Master.">>
<<TalkMC "Good idea, then take everything off.">>
<<TalkNPC _npc "The dress?">>
<<TalkMC "Yes.">>
<<TalkNPC _npc "Yes Master.">>
<<InformationUiPopUp>>She pulls the dress over her head. The moment it's gone her hands move instinctively, one across her chest and one at her hips. She catches herself and looks briefly embarrassed.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mayor/5/05.mp4"/>
<<TalkMC "Why are you covering yourself?">>
<<TalkNPC _npc "Sor- sorry, Master. It's still a little strange for me. We've already done it together and yet standing here, naked, like this, just still while you look, it's completely different.">>
<<TalkMC "You have nothing to hide. Relax, don't be stressed, you look incredible like this.">>
<<TalkNPC _npc "Yes, it was just instinct.">>
<<TalkMC "...">>
<<TalkMC "Where's the bathroom?">>
<<TalkNPC _npc "Down the hall, second door on the left.">>
<<InformationUiPopUp>>I stand, move close behind her, she goes completely still, then I speak near her ear. I bring my hand down hard on one cheek. She inhales, surprised, and doesn't move. Then I gesture for her to go ahead.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mayor/5/06.mp4"/>
<<TalkMC "Let's go.">>
<<TalkNPC _npc "Yes, Master.">>
<<InformationUiPopUp>>Once in the bathroom, an Italian shower, a wide tiled space, rainfall head. I sit on the closed toilet beside it and gesture for her to get in. She steps inside and turns the water on.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mayor/5/07.mp4"/>
<<TalkMC "This will help you relax. And don't worry, take your time, let me enjoy the view.">>
<<TalkNPC _npc "It's strange being watched. Not bad. Just... it's a first for me.">>
<<TalkNPC _npc "...">>
<<TalkNPC _npc "Do you want me to do something, or just shower?">>
<<TalkMC "Just shower. I'll tell you when we move on.">>
<<TalkNPC _npc "Understood.">>
<<InformationUiPopUp>>When she finishes she stands still, the water still running, waiting for me to tell her what to do. I stand, reach in and turn it off, then step back.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mayor/5/08.mp4"/>
<<TalkMC "Good, go to the living room, where we were sitting.">>
<<InformationUiPopUp>>She moves there, I follow right behind. Once back in the living room, I look around and spot a paddle racket, then I order her onto the coffee table.
<</InformationUiPopUp>>
<<TalkMC "On the table on all fours.">>
<<TalkNPC _npc "The coffee table?">>
<<TalkMC "Yes, on the coffee table.">>
<<TalkNPC _npc "As you wish, Master.">>
<<InformationUiPopUp>>She climbs on carefully and settles onto all fours, back level, head down.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mayor/5/09.mp4"/>
<<InformationUiPopUp>>I move to pick up the paddle racket, then come back and bring it down across her ass, sharp. Twice. Three times. She grips the table edge and stays exactly where she is, letting out small surprised cries.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mayor/5/10.mp4"/>
<<TalkNPC _npc "<em>Ah!</em>">>
<<TalkNPC _npc "I'm surprised to find I love this, it's thanks to you Master. Thank you.">>
<<TalkMC "<em>Shhh...</em>">>
<<TalkMC "Show me where the bedroom is.">>
<<TalkNPC _npc "Follow me, I'll show you Master.">>
<<InformationUiPopUp>>I follow her to her bedroom, once inside she sits on the edge of the bed, hands folded in her lap, watching me move through the room. I look through her things, her clothes, then pull out a sexy black lace lingerie set and toss it onto the bed beside her.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mayor/5/11.mp4"/>
<<TalkMC "Put that on.">>
<<InformationUiPopUp>>She unfolds the pieces and dresses carefully.
<</InformationUiPopUp>>
<<TalkMC "Stand up now.">>
<<TalkNPC _npc "Yes Master.">>
<<TalkMC "Turn again, let me admire you.">>
<<InformationUiPopUp>>She turns, chin up, slowly. When she completes the rotation she faces me and waits for her next order.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mayor/5/12.mp4"/>
<<TalkMC "Get on all fours on the bed.">>
<<TalkNPC _npc "Right away Master.">>
<<InformationUiPopUp>>She climbs on and settles onto all fours. I undress, stay standing at the edge of the bed, and gesture for her to come toward me.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mayor/5/13.mp4"/>
<<TalkMC "Suck me, and take your time.">>
<<TalkNPC _npc "<em>Mmh... glrk... mmh...</em>">>
<<TalkMC "Slower.">>
<<TalkNPC _npc "Like this?">>
<<TalkNPC _npc "<em>Mmh... glrk...</em>">>
<<TalkMC "Exactly like that.">>
<<InformationUiPopUp>>I sit on the bed. She slides down and kneels on the floor in front of me, continuing to suck me.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mayor/5/14.mp4"/>
<<TalkNPC _npc "<em>Glrk... mmh... ghlk...</em>">>
<<TalkMC "You're incredible... Damn...">>
<<InformationUiPopUp>>After a little while, I give her a new order.
<</InformationUiPopUp>>
<<TalkMC "Come back on the bed.">>
<<TalkNPC _npc "On all fours again?">>
<<TalkMC "Yes, and show me your pussy.">>
<<InformationUiPopUp>>I position myself right behind her, and push into her pussy.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mayor/5/15.mp4"/>
<<TalkNPC _npc "<em>Ah... mmh... yes...</em>">>
<<TalkNPC _npc "Master, please, harder.">>
<<TalkMC "Ask properly.">>
<<TalkNPC _npc "Please, Master. Please harder.">>
<<TalkNPC _npc "<em>Ah... yes... like that...</em>">>
<<TalkMC "Better.">>
<video src="assets/img/story/character/mayor/5/16.mp4"/>
<<TalkNPC _npc "<em>Ah... ah... yes... yes...</em>">>
<<TalkNPC _npc "I can't, I'm going to, please, Master.">>
<<TalkMC "Not yet.">>
<<TalkNPC _npc "...Yes.">>
<video src="assets/img/story/character/mayor/5/17.mp4"/>
<<TalkNPC _npc "<em>Ah... putain... oui... encore...</em>">>
<<InformationUiPopUp>>I pull out, then lie down on my back on the bed beside her. She moves down without being told and sucks me again, slowly and thoroughly.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mayor/5/18.mp4"/>
<<TalkNPC _npc "<em>Glrk... mmh... ghlk...</em>">>
<<TalkMC "Stop, and get on my cock instead.">>
<<TalkNPC _npc "Understood Master.">>
<<TalkNPC _npc "Like this?">>
<<TalkMC "Exactly like that.">>
<video src="assets/img/story/character/mayor/5/19.mp4"/>
<<TalkNPC _npc "<em>Ah... mmh... yes...</em>">>
<<TalkNPC _npc "Tell m-">>
<<TalkNPC _npc "<em>Ah! Oh yes fuck...</em>">>
<<TalkNPC _npc "Tell me what you want.">>
<<TalkMC "Go faster or I'll take over the movement myself.">>
<<InformationUiPopUp>>I let her go at first, then not satisfied enough, I grip her hips and take control entirely, holding her in place and driving everything from below.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mayor/5/20.mp4"/>
<<TalkNPC _npc "<em>Ah... ah... yes... yes...</em>">>
<<TalkNPC _npc "Master, I...">>
<<TalkMC "No, not yet.">>
<<TalkNPC _npc "<em>Ah... putain... encore...</em>">>
<<TalkNPC _npc "Okay I... I'll hold it...">>
<video src="assets/img/story/character/mayor/5/21.mp4"/>
<<TalkNPC _npc "<em>Ah... ah... yes... yes...</em>">>
<<InformationUiPopUp>>I stop, then give her another order.
<</InformationUiPopUp>>
<<TalkMC "Turn around.">>
<<TalkNPC _npc "Now?">>
<<TalkMC "Now.">>
<<TalkNPC _npc "Alright Master.">>
<<InformationUiPopUp>>She turns without lifting off, back to me, hands beside my torso.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mayor/5/22.mp4"/>
<<TalkNPC _npc "Oh God, the angle is...">>
<<TalkNPC _npc "<em>Ah... mmh... yes...</em>">>
<<TalkMC "Keep moving.">>
<<TalkNPC _npc "Yes, yes, Master.">>
<video src="assets/img/story/character/mayor/5/23.mp4"/>
<<TalkNPC _npc "<em>Ah... ah... yes... yes...</em>">>
<<TalkNPC _npc "Can I, Master, please, can I...">>
<<TalkMC "No. Still not time!">>
<<TalkNPC _npc "...Yes, sorry Master.">>
<<InformationUiPopUp>>I end up pushing her to the side.
<</InformationUiPopUp>>
<<TalkMC "Get back on all fours again.">>
<<TalkNPC _npc "As you wish Master.">>
<<InformationUiPopUp>>She repositions immediately without hesitating.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mayor/5/24.mp4"/>
<<TalkNPC _npc "<em>Ah... mmh... yes... Master...</em>">>
<<TalkNPC _npc "Please, Master, please let me, I can't...">>
<<TalkMC "Wait a little longer!">>
<<TalkNPC _npc "Yes, Master. Yes.">>
<video src="assets/img/story/character/mayor/5/25.mp4"/>
<<TalkNPC _npc "<em>Ah... ah... yes... yes...</em>">>
<<InformationUiPopUp>>I flip her onto her back, move between her legs, and push into her pussy again without stopping. She wraps her legs around me and doesn't look away.
<</InformationUiPopUp>>
<<TalkNPC _npc "Master.">>
<<TalkMC "Look at me.">>
<<TalkNPC _npc "I'm looking at you Master. I'm only looking at you Master!">>
<<TalkNPC _npc "<em>Ah... mmh... yes... yes...</em>">>
<<TalkMC "Good.">>
<<TalkNPC _npc "Please. Please now. Please, Master.">>
<<TalkMC "Go ahead! Now you can!">>
<<TalkNPC _npc "<em>Ah... ah... yes... yes... fuck yes...</em>">>
<<TalkNPC _npc "Oh yes! Thank you Master! Thank you... I love you so much...">>
<<InformationUiPopUp>>I come inside her, deep, holding until it's completely done. She doesn't close her eyes once.
<</InformationUiPopUp>>
<video src="assets/img/story/character/mayor/5/26.mp4"/>
<<TalkNPC _npc "...">>
<<TalkMC "You were amazing.">>
<<TalkNPC _npc "Thank you Master, truly.">>
<<TalkMC "How do you feel?">>
<<TalkNPC _npc "Like I'm completely free. I don't want to move, I don't want you to leave, just stay here by your side. Be completely yours, for as long as you want me.">>
<<TalkMC "I'll stay a little longer then, you deserve it.">>
<<TalkNPC _npc "Thank you Master! I'll do everything you ask. Absolutely everything...">><<set $NPCMayorHouseAccess = true>><</revealtext>>
/* ====================================================
*
* -------------------------------- REPLAY CHAPTER --------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl > 5>><<set $SaveTalklvl = _npc.talklvl>><<set _npc.replaytalk = true>><<set _gotoReplayNpc = "Talk." + _npc.id>>
<<passagebg>><img src="assets/background.gif"/><</passagebg>>
<style>.rCard a{display:flex;align-items:center;gap:clamp(6px,1vw,10px);padding:clamp(8px,1.2vw,11px) clamp(10px,1.5vw,16px);border-radius:10px;background:rgba(230,87,99,.07);border:1px solid rgba(230,87,99,.18);text-decoration:none;transition:background .15s;}.rCard a:hover{background:rgba(230,87,99,.14);border-color:rgba(230,87,99,.35);}.rCard .rNum{font-size:calc(clamp(14px,1.8vw,18px) + var(--font-boost,0px));font-weight:950;color:rgba(255,255,255,.92);}.rCard .rLabel{font-size:calc(clamp(9px,1vw,12px) + var(--font-boost,0px));font-weight:900;letter-spacing:.16em;text-transform:uppercase;color:rgba(230,87,99,.55);}.rCard .rArrow{margin-left:auto;font-size:calc(clamp(9px,1vw,12px) + var(--font-boost,0px));font-weight:900;letter-spacing:.1em;color:rgba(230,87,99,.45);}</style><div style="display:flex;flex-direction:column;gap:6px;width:100%;margin-top:6px;"><div style="font-size:calc(clamp(9px,1vw,12px) + var(--font-boost,0px));font-weight:900;letter-spacing:.16em;text-transform:uppercase;color:rgba(255,255,255,.18);margin-bottom:6px;text-align:center;">— Select a scene to replay —</div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>01</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 0>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>02</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 1>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>03</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 2>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>04</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 3>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>05</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 4>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>06</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 5>><<goto _gotoReplayNpc>><</link>></div></div>
<</if>><</if>><div class="BottomUiBarCustom">
<<if _npc.talklvl == 0>><<BottomButton "Decision">><<revealbtn "chapter1" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 1>><<BottomButton "Decision">><<revealbtn "chapter2" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 2>><<BottomButton "Decision">><<revealbtn "chapter3" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 3>><<BottomButton "Decision">><<revealbtn "chapter4" "🧠 Use power" "moveBtn">><<UsePsychicPower>><<set $MayorStoryInfoForSMS = true>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 4>><<BottomButton "Decision">><<revealbtn "chapter5" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 5>><<BottomButton "Decision">><<revealbtn "chapter6" "🧠 Use power" "" "powerid" "enterid" true>><<UsePsychicPower>><</revealbtn>><<revealbtn "enter" "➡️ Enter" "moveBtn" "enterid" "" false>><<bgpause>><</revealbtn>><</BottomButton>><</if>>
<<BottomButton "Move" "moveBtn">><<if $FromOtherPlace == true>><<link "↩️ Return">><<if _npc.replaytalk == false>><<set _npc.talklvl++>><<set _npc.lvl++>><<set $PsychicPower -= 1>><<if _NextTime == true>><<set $Time++>><<set _NextTime = false>><</if>><<else>><<set _npc.talklvl = $SaveTalklvl>><<set _npc.replaytalk = false>><</if>><<ReturnToGoto>><<set $FromOtherPlace = false>><</link>><<else>><<link "↩️ Return">><<if _npc.replaytalk == false>><<set _npc.talklvl++>><<set _npc.lvl++>><<set $PsychicPower -= 1>><<if _NextTime == true>><<set $Time++>><<set _NextTime = false>><</if>><<if _npc.lvl == 5>><<set $Inventory.buildingpermitdocument = {id:"buildingpermitdocument", name:"Building Permit Document", price:0, img:"assets/img/items/story/buildingpermitdocument.webp", unique:true, inventory:true, bought:true, desc:"A useful item for the story.", qty:1}>><</if>><<else>><<set _npc.talklvl = $SaveTalklvl>><<set _npc.replaytalk = false>><</if>><<bgpause>><<if $MayorStoryInfo5 == false and _npc.replaytalk == false and _npc.talklvl == 1>><<goto "MayorStory8">><<else>><<goto _gotoNpc>><</if>><</link>><</if>><</BottomButton>>
</div><<sound "music" "music.music" true>><<set _raw = $ActiveNPC>><<if !_raw or _raw.id is undefined>>Invalid NPC.<<else>><<set _id = String(_raw.id)>><<set _key = "NPC" + _id>><<run State.temporary.npcObj = State.variables[State.temporary.key] || State.variables[_key]>><<set _npc = _npcObj>><<set _gotoNpc = _npc.id + ".interact">>
/* ====================================================
*
* ----------------------------------- CHAPTER 1 -----------------------------------------
*
*/ ====================================================
<<if _npc.talklvl == 0>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><</if>>
<<passagebg>><img src="assets/img/misc/???.png"/><</passagebg>>
<<InformationUiPopUp>>
<</InformationUiPopUp>>
<<TalkMC "">>
<<TalkNPC _npc "">>
/* ====================================================
*
* ----------------------------------- CHAPTER 2 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 1>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><</if>>
<<passagebg>><img src="assets/img/misc/???.png"/><</passagebg>>
<<InformationUiPopUp>>
<</InformationUiPopUp>>
<<TalkMC "">>
<<TalkNPC _npc "">>
/* ====================================================
*
* ----------------------------------- CHAPTER 3 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 2>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><</if>>
<<passagebg>><img src="assets/img/misc/???.png"/><</passagebg>>
<<InformationUiPopUp>>
<</InformationUiPopUp>>
<<TalkMC "">>
<<TalkNPC _npc "">>
/* ====================================================
*
* ----------------------------------- CHAPTER 4 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 3>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><</if>>
<<passagebg>><img src="assets/img/misc/???.png"/><</passagebg>>
<<InformationUiPopUp>>
<</InformationUiPopUp>>
<<TalkMC "">>
<<TalkNPC _npc "">>
/* ====================================================
*
* ----------------------------------- CHAPTER 5 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 4>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><</if>>
<<passagebg>><img src="assets/img/misc/???.png"/><</passagebg>>
<<InformationUiPopUp>>
<</InformationUiPopUp>>
<<TalkMC "">>
<<TalkNPC _npc "">>
/* ====================================================
*
* ----------------------------------- CHAPTER 6 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 5>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><</if>>
<<passagebg>><img src="assets/img/misc/???.png"/><</passagebg>>
<<InformationUiPopUp>>
<</InformationUiPopUp>>
<<TalkMC "">>
<<TalkNPC _npc "">>
/* ====================================================
*
* -------------------------------- REPLAY CHAPTER --------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl > 5>><<set $SaveTalklvl = _npc.talklvl>><<set _npc.replaytalk = true>><<set _gotoReplayNpc = "Talk." + _npc.id>>
<<passagebg>><img src="assets/background.gif"/><</passagebg>>
<style>.rCard a{display:flex;align-items:center;gap:clamp(6px,1vw,10px);padding:clamp(8px,1.2vw,11px) clamp(10px,1.5vw,16px);border-radius:10px;background:rgba(230,87,99,.07);border:1px solid rgba(230,87,99,.18);text-decoration:none;transition:background .15s;}.rCard a:hover{background:rgba(230,87,99,.14);border-color:rgba(230,87,99,.35);}.rCard .rNum{font-size:calc(clamp(14px,1.8vw,18px) + var(--font-boost,0px));font-weight:950;color:rgba(255,255,255,.92);}.rCard .rLabel{font-size:calc(clamp(9px,1vw,12px) + var(--font-boost,0px));font-weight:900;letter-spacing:.16em;text-transform:uppercase;color:rgba(230,87,99,.55);}.rCard .rArrow{margin-left:auto;font-size:calc(clamp(9px,1vw,12px) + var(--font-boost,0px));font-weight:900;letter-spacing:.1em;color:rgba(230,87,99,.45);}</style><div style="display:flex;flex-direction:column;gap:6px;width:100%;margin-top:6px;"><div style="font-size:calc(clamp(9px,1vw,12px) + var(--font-boost,0px));font-weight:900;letter-spacing:.16em;text-transform:uppercase;color:rgba(255,255,255,.18);margin-bottom:6px;text-align:center;">— Select a scene to replay —</div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>01</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 0>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>02</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 1>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>03</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 2>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>04</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 3>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>05</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 4>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>06</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 5>><<goto _gotoReplayNpc>><</link>></div></div>
<</if>><</if>><div class="BottomUiBarCustom">
<<if _npc.talklvl == 0>><<BottomButton "Decision">><<revealbtn "chapter1" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 1>><<BottomButton "Decision">><<revealbtn "chapter2" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 2>><<BottomButton "Decision">><<revealbtn "chapter3" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 3>><<BottomButton "Decision">><<revealbtn "chapter4" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 4>><<BottomButton "Decision">><<revealbtn "chapter5" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 5>><<BottomButton "Decision">><<revealbtn "chapter6" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><</if>>
<<BottomButton "Move" "moveBtn">><<if $FromOtherPlace == true>><<link "↩️ Return">><<if _npc.replaytalk == false>><<set _npc.talklvl++>><<set _npc.lvl++>><<set $PsychicPower -= 1>><<if _NextTime == true>><<set $Time++>><<set _NextTime = false>><</if>><<else>><<set _npc.talklvl = $SaveTalklvl>><<set _npc.replaytalk = false>><</if>><<ReturnToGoto>><<set $FromOtherPlace = false>><</link>><<else>><<link "↩️ Return">><<if _npc.replaytalk == false>><<set _npc.talklvl++>><<set _npc.lvl++>><<set $PsychicPower -= 1>><<if _NextTime == true>><<set $Time++>><<set _NextTime = false>><</if>><<else>><<set _npc.talklvl = $SaveTalklvl>><<set _npc.replaytalk = false>><</if>><<bgpause>><<goto _gotoNpc>><</link>><</if>><</BottomButton>>
</div><<sound "music" "music.music" true>><<set _raw = $ActiveNPC>><<if !_raw or _raw.id is undefined>>Invalid NPC.<<else>><<set _id = String(_raw.id)>><<set _key = "NPC" + _id>><<run State.temporary.npcObj = State.variables[State.temporary.key] || State.variables[_key]>><<set _npc = _npcObj>><<set _gotoNpc = _npc.id + ".interact">>
/* ====================================================
*
* ----------------------------------- CHAPTER 1 -----------------------------------------
*
*/ ====================================================
<<if _npc.talklvl == 0>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><</if>>
<<passagebg>><img src="assets/img/misc/???.png"/><</passagebg>>
<<InformationUiPopUp>>
<</InformationUiPopUp>>
<<TalkMC "">>
<<TalkNPC _npc "">>
/* ====================================================
*
* ----------------------------------- CHAPTER 2 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 1>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><</if>>
<<passagebg>><img src="assets/img/misc/???.png"/><</passagebg>>
<<InformationUiPopUp>>
<</InformationUiPopUp>>
<<TalkMC "">>
<<TalkNPC _npc "">>
/* ====================================================
*
* ----------------------------------- CHAPTER 3 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 2>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><</if>>
<<passagebg>><img src="assets/img/misc/???.png"/><</passagebg>>
<<InformationUiPopUp>>
<</InformationUiPopUp>>
<<TalkMC "">>
<<TalkNPC _npc "">>
/* ====================================================
*
* ----------------------------------- CHAPTER 4 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 3>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><</if>>
<<passagebg>><img src="assets/img/misc/???.png"/><</passagebg>>
<<InformationUiPopUp>>
<</InformationUiPopUp>>
<<TalkMC "">>
<<TalkNPC _npc "">>
/* ====================================================
*
* ----------------------------------- CHAPTER 5 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 4>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><</if>>
<<passagebg>><img src="assets/img/misc/???.png"/><</passagebg>>
<<InformationUiPopUp>>
<</InformationUiPopUp>>
<<TalkMC "">>
<<TalkNPC _npc "">>
/* ====================================================
*
* ----------------------------------- CHAPTER 6 -----------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl == 5>><<if _npc.replaytalk == true>><<else>><<set _npc.lastCorruptDay = $Day>><<set _npc.lastCorruptBool = true>><<set _NextTime = true>><</if>>
<<passagebg>><img src="assets/img/misc/???.png"/><</passagebg>>
<<InformationUiPopUp>>
<</InformationUiPopUp>>
<<TalkMC "">>
<<TalkNPC _npc "">>
/* ====================================================
*
* -------------------------------- REPLAY CHAPTER --------------------------------------
*
*/ ====================================================
<<elseif _npc.talklvl > 5>><<set $SaveTalklvl = _npc.talklvl>><<set _npc.replaytalk = true>><<set _gotoReplayNpc = "Talk." + _npc.id>>
<<passagebg>><img src="assets/background.gif"/><</passagebg>>
<style>.rCard a{display:flex;align-items:center;gap:clamp(6px,1vw,10px);padding:clamp(8px,1.2vw,11px) clamp(10px,1.5vw,16px);border-radius:10px;background:rgba(230,87,99,.07);border:1px solid rgba(230,87,99,.18);text-decoration:none;transition:background .15s;}.rCard a:hover{background:rgba(230,87,99,.14);border-color:rgba(230,87,99,.35);}.rCard .rNum{font-size:calc(clamp(14px,1.8vw,18px) + var(--font-boost,0px));font-weight:950;color:rgba(255,255,255,.92);}.rCard .rLabel{font-size:calc(clamp(9px,1vw,12px) + var(--font-boost,0px));font-weight:900;letter-spacing:.16em;text-transform:uppercase;color:rgba(230,87,99,.55);}.rCard .rArrow{margin-left:auto;font-size:calc(clamp(9px,1vw,12px) + var(--font-boost,0px));font-weight:900;letter-spacing:.1em;color:rgba(230,87,99,.45);}</style><div style="display:flex;flex-direction:column;gap:6px;width:100%;margin-top:6px;"><div style="font-size:calc(clamp(9px,1vw,12px) + var(--font-boost,0px));font-weight:900;letter-spacing:.16em;text-transform:uppercase;color:rgba(255,255,255,.18);margin-bottom:6px;text-align:center;">— Select a scene to replay —</div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>01</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 0>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>02</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 1>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>03</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 2>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>04</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 3>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>05</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 4>><<goto _gotoReplayNpc>><</link>></div><div class="rCard"><<link "<span class='rLabel'>SCENE</span><span class='rNum'>06</span><span class='rArrow'>REPLAY ›</span>">><<set _npc.talklvl = 5>><<goto _gotoReplayNpc>><</link>></div></div>
<</if>><</if>><div class="BottomUiBarCustom">
<<if _npc.talklvl == 0>><<BottomButton "Decision">><<revealbtn "chapter1" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 1>><<BottomButton "Decision">><<revealbtn "chapter2" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 2>><<BottomButton "Decision">><<revealbtn "chapter3" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 3>><<BottomButton "Decision">><<revealbtn "chapter4" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 4>><<BottomButton "Decision">><<revealbtn "chapter5" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><<elseif _npc.talklvl == 5>><<BottomButton "Decision">><<revealbtn "chapter6" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>><</if>>
<<BottomButton "Move" "moveBtn">><<if $FromOtherPlace == true>><<link "↩️ Return">><<if _npc.replaytalk == false>><<set _npc.talklvl++>><<set _npc.lvl++>><<set $PsychicPower -= 1>><<if _NextTime == true>><<set $Time++>><<set _NextTime = false>><</if>><<else>><<set _npc.talklvl = $SaveTalklvl>><<set _npc.replaytalk = false>><</if>><<ReturnToGoto>><<set $FromOtherPlace = false>><</link>><<else>><<link "↩️ Return">><<if _npc.replaytalk == false>><<set _npc.talklvl++>><<set _npc.lvl++>><<set $PsychicPower -= 1>><<if _NextTime == true>><<set $Time++>><<set _NextTime = false>><</if>><<else>><<set _npc.talklvl = $SaveTalklvl>><<set _npc.replaytalk = false>><</if>><<bgpause>><<goto _gotoNpc>><</link>><</if>><</BottomButton>>
</div><<sound "music" "music.music" true>><<sound "bg" "bg.empty" true>><<passagebg>><img src="assets/img/misc/oldtown/redlight/sexshop.webp"/><</passagebg>>
<<if $Time !== 0>><<Interact $NPCSexShop>><<else>><<InformationUiPopUp "Interact">>There is no one.<</InformationUiPopUp>><</if>>
<<set _shopVar = "ShopSexshop">><<set _shop to State.variables[_shopVar]>><style>
.shp-wrap{display:flex;flex-direction:column;gap:14px;padding:4px 2px;}
.shp-topbar{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;padding:clamp(8px,2vw,12px) clamp(10px,2vw,16px);border-radius:14px;background:rgba(0,0,0,.45);border:1px solid rgba(255,255,255,.10);}
.shp-topbar-title{font-size:calc(24px + var(--font-boost,0px));font-weight:950;color:rgba(255,255,255,.96);letter-spacing:-.01em;}
.shp-balances{display:flex;gap:10px;flex-wrap:wrap;}
.shp-bal{display:flex;flex-direction:column;align-items:flex-end;gap:2px;padding:8px 14px;border-radius:10px;background:rgba(0,0,0,.45);border:1px solid rgba(255,255,255,.10);}
.shp-bal-label{font-size:calc(14px + var(--font-boost,0px));font-weight:900;letter-spacing:.12em;text-transform:uppercase;color:rgba(255,255,255,.65);}
.shp-bal-value{font-size:calc(16px + var(--font-boost,0px));font-weight:950;color:rgba(255,255,255,.96);letter-spacing:-.01em;}
.shp-grid{display:grid;grid-template-columns:repeat(auto-fill, minmax(clamp(140px,15vw,170px), 1fr));gap:10px;}
.shp-card{display:flex;flex-direction:column;border-radius:14px;background:rgba(0,0,0,.45);border:1px solid rgba(255,255,255,.10);overflow:hidden;transition:border-color .14s, background .14s, transform .14s;}
.shp-card:hover{border-color:rgba(255,255,255,.20);background:rgba(0,0,0,.35);transform:translateY(-2px);}
.shp-card-img-wrap{width:100%;aspect-ratio:1;background:#f0f0f0;display:flex;align-items:center;justify-content:center;line-height:0;font-size:0;}
.shp-card-img-wrap img{width:100%!important;height:100%!important;min-width:unset!important;max-width:unset!important;min-height:unset!important;max-height:unset!important;object-fit:contain!important;display:block!important;margin:0!important;}
.shp-card-body{display:flex;flex-direction:column;gap:6px;padding:clamp(8px,2vw,10px) clamp(8px,2vw,10px) clamp(10px,2vw,12px);flex:1 1 auto;}
.shp-card-name{font-size:calc(15px + var(--font-boost,0px));font-weight:950;color:rgba(255,255,255,.96);letter-spacing:.01em;line-height:1.2;}
.shp-card-desc{font-size:calc(14px + var(--font-boost,0px));color:rgba(255,255,255,.75);font-weight:600;line-height:1.35;flex:1 1 auto;}
.shp-card-price{font-size:calc(16px + var(--font-boost,0px));font-weight:950;color:#e65763;letter-spacing:-.01em;}
.shp-card-actions{display:grid;grid-template-columns:1fr 1fr;gap:6px;margin-top:2px;}
.shp-btn{padding:8px 0;border-radius:9px;border:1px solid rgba(230,87,99,.40);background:rgba(230,87,99,.14);color:rgba(230,87,99,.98);font-weight:950;font-size:calc(14px + var(--font-boost,0px));letter-spacing:.08em;text-align:center;cursor:pointer;user-select:none;transition:background .12s, border-color .12s;text-decoration:none!important;display:block;}
.shp-btn:hover{background:rgba(230,87,99,.24);border-color:rgba(230,87,99,.60);}
.shp-btn-disabled{opacity:.45;pointer-events:none;display:block;width:100%;padding:8px 0;border-radius:9px;border:1px solid rgba(255,255,255,.15);background:rgba(0,0,0,.40);color:rgba(255,255,255,.60);font-weight:950;font-size:calc(14px + var(--font-boost,0px));letter-spacing:.08em;text-align:center;box-sizing:border-box;}
</style><div class="shp-wrap"><div class="shp-topbar"><div><div class="shp-topbar-title">Sexshop Store</div></div><div class="shp-balances"><div class="shp-bal"><div class="shp-bal-label">Money</div><div class="shp-bal-value">$<<=$Money>></div></div><div class="shp-bal"><div class="shp-bal-label">Bank</div><div class="shp-bal-value">$<<=$Bank>></div></div></div></div><div class="shp-grid"><<for _i = 0; _i < _shop.length; _i++>><<set _p = _shop[_i]>><<if !(_p.unique && _p.bought)>><div class="shp-card"><div class="shp-card-img-wrap"><<if _p.img and _p.img !== "">><<= '<img src="'+_p.img+'" alt="'+_p.name+'">'>><<else>><span style="font-size:14px;opacity:.5;color:#000;">No image</span><</if>></div><div class="shp-card-body"><div class="shp-card-name"><<= _p.name>></div><div class="shp-card-desc"><<if _p.desc == "">>—<<else>><<= _p.desc>><</if>></div><div class="shp-card-price">$<<= +_p.price>></div><<capture _i _p>><div class="shp-card-actions"><<if $Money >= +_p.price>><div><<link "<div class='shp-btn'>MONEY</div>">><<if $Money >= +_p.price>><<set $Money -= +_p.price>><<if _p.inventory>><<set $Inventory[_p.id] to $Inventory[_p.id] or {id:_p.id, name:_p.name, img:_p.img or "", qty:0, desc:_p.desc or ""}>><<if !$Inventory[_p.id].desc and _p.desc>><<set $Inventory[_p.id].desc = _p.desc>><</if>><<set $Inventory[_p.id].qty += 1>><</if>><<set _p.bought = true>><<Refresh>><</if>><</link>></div><<else>><div class="shp-btn-disabled">MONEY</div><</if>><<if $Bank >= +_p.price>><div><<link "<div class='shp-btn'>BANK</div>">><<if $Bank >= +_p.price>><<set $Bank -= +_p.price>><<if _p.inventory>><<set $Inventory[_p.id] to $Inventory[_p.id] or {id:_p.id, name:_p.name, img:_p.img or "", qty:0, desc:_p.desc or ""}>><<if !$Inventory[_p.id].desc and _p.desc>><<set $Inventory[_p.id].desc = _p.desc>><</if>><<set $Inventory[_p.id].qty += 1>><</if>><<set _p.bought = true>><<Refresh>><</if>><</link>></div><<else>><div class="shp-btn-disabled">BANK</div><</if>></div><</capture>></div></div><</if>><</for>></div></div>
<div class="BottomUiBarCustom">
<<BottomButton "Move">>[[🚪 Exit|RedLightDistrict]]<</BottomButton>>
</div><<sound "music" "music.music" true>><<sound "bg" "bg.empty" true>><<passagebg>><<if $Time !== 3>><img src="assets/img/misc/oldtown/traphouse/traphouse.webp"/><<else>><img src="assets/img/misc/oldtown/traphouse/traphousenight.webp"/><</if>><</passagebg>><<if $Reputation < 50>><<TalkRandom "Dealer" "assets/img/character/npc/b3.jpg" "Get out of here!">><<elseif $Reputation >= 50 & $TalkDealer2 == false>><<if $TalkDealer1 == false>><<goto "StoryTalkDealer1">><</if>><<TalkRandom "<<if $TalkDealer2 == true>>W. <em>(Dealer)</em><<else>>Dealer<</if>>" "assets/img/character/npc/b3.jpg" "You still haven't understood?! Get out of here!">><<elseif $Reputation >= 75 & $TalkDealer2 == true & $TalkDealer3 == false>><<goto "StoryTalkDealer2">><<elseif $Reputation >= 75 & $TalkDealer3 == true>><<if $MayorStoryEncounter3 == true and $MayorStoryEncounter3Goto == false>><<goto "MayorStory14">><<set $MayorStoryEncounter3Goto = true>><<elseif $MayorStory9 == true and $MayorStoryFinish == false>><<TalkRandom "W. <em>(Dealer)</em>" "assets/img/character/npc/b3.jpg" "You still haven't understood?! Get out of here!">><<else>><<TalkRandom "W. <em>(Dealer)</em>" "assets/img/character/npc/b3.jpg" "Choose what you want.">>
<<set _shopVar = "ShopTrapHouse">><<set _shop to State.variables[_shopVar]>><<if !$ShopBuyQty>><<set $ShopBuyQty = {}>><</if>><style>
.shp-wrap{display:flex;flex-direction:column;gap:14px;padding:4px 2px;}
.shp-topbar{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;padding:clamp(8px,2vw,12px) clamp(10px,2vw,16px);border-radius:14px;background:rgba(0,0,0,.45);border:1px solid rgba(255,255,255,.10);}
.shp-topbar-title{font-size:calc(24px + var(--font-boost,0px));font-weight:950;color:rgba(255,255,255,.96);letter-spacing:-.01em;}
.shp-balances{display:flex;gap:10px;flex-wrap:wrap;}
.shp-bal{display:flex;flex-direction:column;align-items:flex-end;gap:2px;padding:8px 14px;border-radius:10px;background:rgba(0,0,0,.45);border:1px solid rgba(255,255,255,.10);}
.shp-bal-label{font-size:calc(14px + var(--font-boost,0px));font-weight:900;letter-spacing:.12em;text-transform:uppercase;color:rgba(255,255,255,.65);}
.shp-bal-value{font-size:calc(16px + var(--font-boost,0px));font-weight:950;color:rgba(255,255,255,.96);letter-spacing:-.01em;}
.shp-grid{display:grid;grid-template-columns:repeat(auto-fill, minmax(clamp(140px,15vw,170px), 1fr));gap:10px;}
.shp-card{display:flex;flex-direction:column;border-radius:14px;background:rgba(0,0,0,.45);border:1px solid rgba(255,255,255,.10);overflow:hidden;transition:border-color .14s, background .14s, transform .14s;}
.shp-card:hover{border-color:rgba(255,255,255,.20);background:rgba(0,0,0,.35);transform:translateY(-2px);}
.shp-card-img-wrap{width:100%;aspect-ratio:1;background:#f0f0f0;display:flex;align-items:center;justify-content:center;line-height:0;font-size:0;}
.shp-card-img-wrap img{width:100%!important;height:100%!important;min-width:unset!important;max-width:unset!important;min-height:unset!important;max-height:unset!important;object-fit:contain!important;display:block!important;margin:0!important;}
.shp-card-body{display:flex;flex-direction:column;gap:6px;padding:clamp(8px,2vw,10px) clamp(8px,2vw,10px) clamp(10px,2vw,12px);flex:1 1 auto;}
.shp-card-name{font-size:calc(15px + var(--font-boost,0px));font-weight:950;color:rgba(255,255,255,.96);letter-spacing:.01em;line-height:1.2;}
.shp-card-desc{font-size:calc(14px + var(--font-boost,0px));color:rgba(255,255,255,.75);font-weight:600;line-height:1.35;flex:1 1 auto;}
.shp-card-price{font-size:calc(16px + var(--font-boost,0px));font-weight:950;color:#e65763;letter-spacing:-.01em;}
.shp-card-qty{display:grid;grid-template-columns:64px 1fr;align-items:center;gap:6px;margin-top:2px;}
.shp-card-qty input{width:100%!important;padding:7px 4px;border-radius:8px;border:1px solid rgba(255,255,255,.20);background:rgba(0,0,0,.50);color:rgba(255,255,255,.96);font-size:calc(14px + var(--font-boost,0px));font-weight:700;text-align:center;box-sizing:border-box;-moz-appearance:textfield;}
.shp-card-qty input::-webkit-outer-spin-button,.shp-card-qty input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0;}
.shp-btn{padding:8px 0;border-radius:9px;border:1px solid rgba(230,87,99,.40);background:rgba(230,87,99,.14);color:rgba(230,87,99,.98);font-weight:950;font-size:calc(14px + var(--font-boost,0px));letter-spacing:.08em;text-align:center;cursor:pointer;user-select:none;transition:background .12s, border-color .12s;text-decoration:none!important;display:block;}
.shp-btn:hover{background:rgba(230,87,99,.24);border-color:rgba(230,87,99,.60);}
.shp-btn-disabled{opacity:.45;pointer-events:none;display:block;width:100%;padding:8px 0;border-radius:9px;border:1px solid rgba(255,255,255,.15);background:rgba(0,0,0,.40);color:rgba(255,255,255,.60);font-weight:950;font-size:calc(14px + var(--font-boost,0px));letter-spacing:.08em;text-align:center;box-sizing:border-box;}
</style><div class="shp-wrap"><div class="shp-topbar"><div><div class="shp-topbar-title">Trap House</div></div><div class="shp-balances"><div class="shp-bal"><div class="shp-bal-label">Money</div><div class="shp-bal-value">$<<=$Money>></div></div></div></div><div class="shp-grid"><<for _i = 0; _i < _shop.length; _i++>><<set _p = _shop[_i]>><<if !(_p.unique && _p.bought)>><div class="shp-card"><div class="shp-card-img-wrap"><<if _p.img and _p.img !== "">><<= '<img src="'+_p.img+'" alt="'+_p.name+'">'>><<else>><span style="font-size:14px;opacity:.5;color:#000;display:block;padding:20px;text-align:center;">No image</span><</if>></div><div class="shp-card-body"><div class="shp-card-name"><<= _p.name>></div><div class="shp-card-desc"><<if _p.desc == "">>—<<else>><<= _p.desc>><</if>></div><div class="shp-card-price">$<<= +_p.price>> / unit</div><<capture _i _p>><<set _unit = +_p.price>><<set _maxByCash = (_unit > 0) ? Math.floor($Money / _unit) : 0>><<if _p.unique>><<set _maxByCash = 1>><</if>><<set _maxByCash = Math.max(1, _maxByCash)>><<if $ShopBuyQty[_p.id] is undefined>><<set $ShopBuyQty[_p.id] = 1>><</if>><<set $ShopBuyQty[_p.id] = Math.max(1, Math.min(+$ShopBuyQty[_p.id] || 1, _maxByCash))>><<set _inputId = "buyqty-" + _p.id>><div class="shp-card-qty"><<= '<input class="buy-qty" id="'+_inputId+'" data-id="'+_p.id+'" data-max="'+_maxByCash+'" type="number" min="1" max="'+_maxByCash+'" step="1" value="'+$ShopBuyQty[_p.id]+'">'>><<if $Money >= +_p.price>><<link "<div class='shp-btn'>BUY</div>">><<set _qty = Math.floor(+$('#'+_inputId).val() || 1)>><<set _unit = +_p.price>><<set _maxByCash = (_unit > 0) ? Math.floor($Money / _unit) : 0>><<if _p.unique>><<set _maxByCash = 1>><</if>><<set _maxByCash = Math.max(1, _maxByCash)>><<set _qty = Math.max(1, Math.min(_qty, _maxByCash))>><<set $ShopBuyQty[_p.id] = _qty>><<run $('#'+_inputId).val(String(_qty))>><<if $Money >= (_qty * _unit)>><<set $Money -= (_qty * _unit)>><<if _p.inventory>><<set $Inventory[_p.id] to $Inventory[_p.id] or {id:_p.id, name:_p.name, img:_p.img or "", qty:0, desc:_p.desc or ""}>><<if !$Inventory[_p.id].desc and _p.desc>><<set $Inventory[_p.id].desc = _p.desc>><</if>><<set $Inventory[_p.id].qty += _qty>><</if>><<if _p.unique>><<set _p.bought = true>><</if>><<Refresh>><</if>><</link>><<else>><div class="shp-btn-disabled">BUY</div><</if>></div><</capture>></div></div><</if>><</for>></div></div>
<<script>>
(function () {
var V = State.variables;
var inputs = Array.prototype.slice.call(document.querySelectorAll('.buy-qty'));
function clamp(n, min, max) {
n = parseInt(n, 10);
if (isNaN(n)) n = min;
if (n < min) n = min;
if (n > max) n = max;
return n;
}
inputs.forEach(function (inp) {
var id = String(inp.getAttribute('data-id') || '').trim();
var max = parseInt(inp.getAttribute('data-max'), 10);
if (!id) return;
if (isNaN(max) || max < 1) max = 1;
if (!V.ShopBuyQty) V.ShopBuyQty = {};
if (V.ShopBuyQty[id] == null) V.ShopBuyQty[id] = 1;
var v = clamp(V.ShopBuyQty[id], 1, max);
V.ShopBuyQty[id] = v;
inp.value = String(v);
var handler = function () {
var m = parseInt(inp.getAttribute('data-max'), 10);
if (isNaN(m) || m < 1) m = 1;
var val = clamp(inp.value, 1, m);
inp.value = String(val);
V.ShopBuyQty[id] = val;
};
inp.addEventListener('input', handler);
inp.addEventListener('change', handler);
});
})();
<</script>><</if>><</if>>
<div class="BottomUiBarCustom"><<if $MayorStoryInfo1 == true and $MayorStoryInfo2 == false and $TalkDealer3 == true>><<BottomButton "Decision">><<link "💬 Ask for equipment">><<goto "MayorStory2">><</link>><</BottomButton>><</if>>
<<BottomButton "Move">>[[🚪 Exit|Oldtown]]<</BottomButton>>
</div><<sound "music" "music.club" true>><<bgpause>><<passagebg>><img src="assets/img/misc/oldtown/redlight/stripclub/stripclub.webp"/><</passagebg>><<set _random = random(9)>><<if _random == 0>>
<video src="assets/img/misc/oldtown/redlight/stripclub/img/01.mp4"/>
<<elseif _random == 1>>
<video src="assets/img/misc/oldtown/redlight/stripclub/img/02.mp4"/>
<<elseif _random == 2>>
<video src="assets/img/misc/oldtown/redlight/stripclub/img/03.mp4"/>
<<elseif _random == 3>>
<video src="assets/img/misc/oldtown/redlight/stripclub/img/04.mp4"/>
<<elseif _random == 4>>
<video src="assets/img/misc/oldtown/redlight/stripclub/img/05.mp4"/>
<<elseif _random == 5>>
<video src="assets/img/misc/oldtown/redlight/stripclub/img/06.mp4"/>
<<elseif _random == 6>>
<video src="assets/img/misc/oldtown/redlight/stripclub/img/07.mp4"/>
<<elseif _random == 7>>
<video src="assets/img/misc/oldtown/redlight/stripclub/img/08.mp4"/>
<<elseif _random == 8>>
<video src="assets/img/misc/oldtown/redlight/stripclub/img/09.mp4"/>
<<elseif _random == 9>>
<video src="assets/img/misc/oldtown/redlight/stripclub/img/10.mp4"/>
<</if>>
<div class="BottomUiBarCustom">
<<BottomButton "Action">><<link "🔞 Choose a stripper">><<goto "ChoiceStripper">><</link>><</BottomButton>>
<<BottomButton "Move">>[[🚪 Exit|RedLightDistrict]]<</BottomButton>>
</div><<sound "music" "music.music" true>><<sound "bg" "bg.empty" true>><<passagebg>><img src="assets/img/misc/home/tv/loading.webp"/><</passagebg>><<if $NPCLandlady.lvl == 4 and $Time == 2 and $Spycam.bathroom == true and $Story4_5Finish == true and $NPCLandlady.lastCorruptBool == false>><<set $FromOtherPlace = true>><<set $ReturnTo = "Bathroom">><<set $ActiveNPC = $NPCLandlady>><<goto "Talk.Landlady">><</if>>
<div class="BottomUiBarCustom">
<<BottomButton "Choice">>[[📰 News Channel|ViewTVNC]]
[[🎞️ Documentary|ViewTVDoc]]
<<if $Time == 3>><<link "🔒 <<print $NPCLandlord.name>> is nearby. You can’t view this content right now.">><</link>><<else>>[[🔞 Adult|ViewTVSex]]<</if>><</BottomButton>>
<<BottomButton "Move">>[[↩️ Stop|HomeLivingRoom]]<</BottomButton>>
</div><<sound "music" "music.music" true>><<sound "bg" "bg.empty" true>><<passagebg>><<set _random = random(4)>><<if _random == 0>>
<img src="assets/img/misc/home/tv/info/01.webp"/>
<<elseif _random == 1>>
<img src="assets/img/misc/home/tv/info/02.webp"/>
<<elseif _random == 2>>
<img src="assets/img/misc/home/tv/info/03.webp"/>
<<elseif _random == 3>>
<img src="assets/img/misc/home/tv/info/04.webp"/>
<<elseif _random == 4>>
<img src="assets/img/misc/home/tv/info/05.webp"/>
<</if>><</passagebg>><<if _random == 0>>
<img src="assets/img/misc/home/tv/info/01.webp"/>
<<elseif _random == 1>>
<img src="assets/img/misc/home/tv/info/02.webp"/>
<<elseif _random == 2>>
<img src="assets/img/misc/home/tv/info/03.webp"/>
<<elseif _random == 3>>
<img src="assets/img/misc/home/tv/info/04.webp"/>
<<elseif _random == 4>>
<img src="assets/img/misc/home/tv/info/05.webp"/>
<</if>>
<div class="BottomUiBarCustom">
<<BottomButton "Choice">>[[📰 News Channel|ViewTVNC]]
[[🎞️ Documentary|ViewTVDoc]]
<<if $Time == 3>><<=$NPCLandlord.name>> is nearby. You can’t view this content right now.<<else>>[[🔞 Adult|ViewTVSex]]<</if>><</BottomButton>>
<<BottomButton "Move">>[[↩️ Stop|HomeLivingRoom]]<</BottomButton>>
</div><<sound "music" "music.music" true>><<sound "bg" "bg.empty" true>><<passagebg>><<set _random = random(2)>><<if _random == 0>>
<img src="assets/img/misc/home/tv/doc/01.webp"/>
<<elseif _random == 1>>
<img src="assets/img/misc/home/tv/doc/02.webp"/>
<<elseif _random == 2>>
<img src="assets/img/misc/home/tv/doc/03.webp"/>
<</if>><</passagebg>><<if _random == 0>>
<img src="assets/img/misc/home/tv/doc/01.webp"/>
<<elseif _random == 1>>
<img src="assets/img/misc/home/tv/doc/02.webp"/>
<<elseif _random == 2>>
<img src="assets/img/misc/home/tv/doc/03.webp"/>
<</if>>
<div class="BottomUiBarCustom">
<<BottomButton "Choice">>[[📰 News Channel|ViewTVNC]]
[[🎞️ Documentary|ViewTVDoc]]
<<if $Time == 3>><<=$NPCLandlord.name>> is nearby. You can’t view this content right now.<<else>>[[🔞 Adult|ViewTVSex]]<</if>><</BottomButton>>
<<BottomButton "Move">>[[↩️ Stop|HomeLivingRoom]]<</BottomButton>>
</div><<sound "music" "music.music" true>><<sound "bg" "bg.empty" true>><<passagebg>><<set _random = random(9)>><<if _random == 0>>
<img src="assets/img/misc/home/tv/x/01.webp"/>
<<elseif _random == 1>>
<img src="assets/img/misc/home/tv/x/02.webp"/>
<<elseif _random == 2>>
<img src="assets/img/misc/home/tv/x/03.webp"/>
<<elseif _random == 3>>
<img src="assets/img/misc/home/tv/x/04.webp"/>
<<elseif _random == 4>>
<img src="assets/img/misc/home/tv/x/05.webp"/>
<<elseif _random == 5>>
<img src="assets/img/misc/home/tv/x/06.webp"/>
<<elseif _random == 6>>
<img src="assets/img/misc/home/tv/x/07.webp"/>
<<elseif _random == 7>>
<img src="assets/img/misc/home/tv/x/08.webp"/>
<<elseif _random == 8>>
<img src="assets/img/misc/home/tv/x/09.webp"/>
<<elseif _random == 9>>
<img src="assets/img/misc/home/tv/x/10.webp"/>
<</if>><</passagebg>><<if _random == 0>>
<img src="assets/img/misc/home/tv/x/01.webp"/>
<<elseif _random == 1>>
<img src="assets/img/misc/home/tv/x/02.webp"/>
<<elseif _random == 2>>
<img src="assets/img/misc/home/tv/x/03.webp"/>
<<elseif _random == 3>>
<img src="assets/img/misc/home/tv/x/04.webp"/>
<<elseif _random == 4>>
<img src="assets/img/misc/home/tv/x/05.webp"/>
<<elseif _random == 5>>
<img src="assets/img/misc/home/tv/x/06.webp"/>
<<elseif _random == 6>>
<img src="assets/img/misc/home/tv/x/07.webp"/>
<<elseif _random == 7>>
<img src="assets/img/misc/home/tv/x/08.webp"/>
<<elseif _random == 8>>
<img src="assets/img/misc/home/tv/x/09.webp"/>
<<elseif _random == 9>>
<img src="assets/img/misc/home/tv/x/10.webp"/>
<</if>><<set $Excitement++>><<if $Excitement >= 10>><<InformationUiPopUp "You just climaxed">>
<<if $Stress <= $StressMin>><em>Stress already at minimum</em><<elseif $Stress > $StressMin>><em>-5 stress</em><<set $Stress -= 5>><</if>><<set $Energy-->><<set $Excitement = 0>>
<</InformationUiPopUp>><</if>>
<div class="BottomUiBarCustom">
<<BottomButton "Choice">>[[📰 News Channel|ViewTVNC]]
[[🎞️ Documentary|ViewTVDoc]]
<<if $Time == 3>><<=$NPCLandlord.name>> is nearby. You can’t view this content right now.<<else>>[[🔞 Adult|ViewTVSex]]<</if>><</BottomButton>>
<<BottomButton "Move">>[[↩️ Stop|HomeLivingRoom]]<</BottomButton>>
</div><<sound "music" "music.music" true>><<set _random = random(9)+1>>
<<DealerSellListItems _random $DrugSellRank $DrugSellPolice $DrugSellOpp $DrugSellType>><<sound "music" "music.music" true>><<sound "bg" "bg.empty" true>><<passagebg>><img src="assets/img/misc/police/policecell.webp"/><</passagebg>>
<div class="BottomUiBarCustom">
<<BottomButton "Move">>[[👮 Reception|Police]]<</BottomButton>>
</div><<sound "music" "music.fight" true>><<passagebg>><img src="assets/img/misc/fight.webp"/><</passagebg>><div id="fight-tip" style="display:none;"></div><div class="fight-ui" style="max-width:960px;margin:auto;"><div id="foe-card" class="foes card" style="display:flex;gap:12px;justify-content:space-between;align-items:center;padding:10px;border:1px solid #444;border-radius:10px;margin-bottom:10px;"><div style="width:100%;"><p style="margin:0;"><strong>Enemy:</strong> <span id="foe-type"></span> (Fitness <span id="foe-lvl"></span>) <span id="foe-states" class="states"></span></p><div class="hp-bar-bg" id="foe-barbg"><div id="foe-bar" class="hp-bar"></div><div class="pop-layer" id="foe-pop"></div></div><p style="margin:4px 0 0 0;">HP <span id="foe-hp"></span> / <span id="foe-max"></span> · 🩹 <span id="foe-band"></span></p></div></div><div id="you-card" class="you card" style="display:flex;gap:12px;justify-content:space-between;align-items:center;padding:10px;border:1px solid #444;border-radius:10px;margin-bottom:14px;"><div style="width:100%;"><p style="margin:0;"><strong>You</strong> (Fitness <span id="player-fit"></span>) <span id="you-states" class="states"></span></p><div class="hp-bar-bg" id="you-barbg"><div id="you-bar" class="hp-bar"></div><div class="pop-layer" id="you-pop"></div></div><div class="sta-row"><span class="sta-label">Stamina</span><div class="sta-bg"><div id="you-sta" class="sta-bar"></div></div><span id="you-sta-txt" class="sta-txt"></span></div><p style="margin:4px 0 0 0;">HP <span id="you-hp"></span> / <span id="you-max"></span> · 🩹 <span id="you-band"></span></p></div></div><div id="fight-actions" style="display:flex;gap:10px;flex-wrap:wrap;margin-bottom:10px;"><button id="btn-atk" type="button" data-tip="Standard attack. Deals solid damage based on your Fitness. Cost: 1 stamina.">🥊 Attack</button><button id="btn-heavy" type="button" data-tip="Heavy attack. Deals 2.5x damage based on Fitness, but costs 2 stamina and misses more often.">💥 Heavy</button><button id="btn-guard" type="button" data-tip="Guard. You take 50% less damage this turn. Cost: 0 stamina. Gain: +1 stamina.">🛡️ Guard</button><button id="btn-heal" type="button" data-tip="Heal using a Medkit. Cooldown: every other turn. Cost: 2 stamina. Requires: 1 Medkit.">🩹 Heal</button><button id="btn-finish" type="button" style="display:none;" data-tip="Finisher. Available when enemy HP is 15% or less. Ends the fight instantly. Cost: 1 stamina.">☠️ Finisher</button></div><div id="fight-popups"></div><div id="fight-stage"></div></div><div class="BottomUiBarCustom"><span style="display: contents;" id="fight-actionsbar"></span></div><style>#fight-tip{position:fixed;z-index:99999;display:none;max-width:280px;padding:8px 10px;border:1px solid rgba(255,255,255,.25);border-radius:10px;background:rgba(10,10,10,.92);backdrop-filter:blur(3px);color:#fff;font-size:.9rem;line-height:1.25;pointer-events:none;box-shadow:0 6px 18px rgba(0,0,0,.35);} .fight-ui p{line-height:1.3;} .fight-ui .card{background:rgba(255,255,255,0.03);} #fight-actions button{padding:8px 12px;border:1px solid #666;border-radius:8px;background:transparent;cursor:pointer;color: #fff;} #fight-actions button:hover{background:rgba(255,255,255,0.06);} #fight-actions button:disabled{opacity:.45;cursor:not-allowed;} .hp-bar-bg{position:relative;height:14px;background:#222;border-radius:7px;overflow:hidden;margin-top:6px;} .hp-bar{height:100%;width:100%;transition:width 250ms ease-in-out,background 250ms linear;} .pop-layer{position:absolute;inset:0;pointer-events:none;overflow:visible;} .dmg-pop{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);font-weight:800;opacity:0;animation:popFloat 650ms ease-out forwards;text-shadow:0 1px 0 rgba(0,0,0,.55);} @keyframes popFloat{0%{opacity:0;transform:translate(-50%,-40%) scale(.9);}15%{opacity:1;}100%{opacity:0;transform:translate(-50%,-140%) scale(1.05);}} .hitFlash{animation:hitFlash 220ms ease-out;} @keyframes hitFlash{0%{filter:none;}40%{filter:brightness(1.35);}100%{filter:none;}} .shake{animation:shake 180ms ease-in-out;} @keyframes shake{0%{transform:translateX(0);}25%{transform:translateX(-3px);}50%{transform:translateX(3px);}75%{transform:translateX(-2px);}100%{transform:translateX(0);}} .attackNudge{animation:attackNudge 160ms ease-in-out;} @keyframes attackNudge{0%{transform:translateX(0);}50%{transform:translateX(3px);}100%{transform:translateX(0);}} .states{font-size:.85rem;opacity:.9;margin-left:8px;} .statePill{display:inline-block;padding:1px 6px;border:1px solid rgba(255,255,255,.25);border-radius:999px;margin-left:6px;font-size:.78rem;} .sta-row{display:flex;align-items:center;gap:8px;margin-top:8px;} .sta-label{font-size:.85rem;opacity:.9;} .sta-bg{height:10px;width:160px;border-radius:6px;background:#222;overflow:hidden;} .sta-bar{height:100%;width:100%;transition:width 200ms ease-in-out;background:#5090e2;} .sta-txt{font-size:.85rem;opacity:.9;min-width:34px;text-align:right;} .fxBadge{display:inline-block;margin-top:6px;font-weight:900;letter-spacing:.3px;opacity:0;animation:fxBadge 650ms ease-out forwards;} @keyframes fxBadge{0%{opacity:0;transform:translateY(2px) scale(.98);}20%{opacity:1;}100%{opacity:0;transform:translateY(-10px) scale(1.02);}}</style>
<<script>>
(function(){
$(document).on(':passagedisplay', function(ev){
if(!ev||!ev.passage||ev.passage.title!=='Fight')return;
const V=State.variables;
const F=V.Fight||(V.Fight={type:"?",lvl:1,playerMax:100,enemyMax:100,playerHP:100,enemyHP:100,playerBand:0,enemyBand:1,playerStaMax:5,playerSta:5,healCD:0,log:[],p:{},e:{}});
const $q=(sel)=>document.querySelector(sel);
function playPunchSfx(){try{if(!window.setup||!setup.AudioMixer)return;setup.AudioMixer.playPlaylist("sfx","sfx.punch",false,{fadeInMs:0,fadeOutMs:0});}catch(e){}}
function shouldPunch(mode){return mode==='atk'||mode==='heavy'||mode==='finish';}
const tip=$q('#fight-tip');
function tipShow(text){if(!tip)return;tip.textContent=text;tip.style.display='block';}
function tipHide(){if(!tip)return;tip.style.display='none';}
function tipMove(e){if(!tip||tip.style.display==='none')return;const pad=14;let x=e.clientX+pad,y=e.clientY+pad;const r=tip.getBoundingClientRect();if(x+r.width>window.innerWidth-8)x=e.clientX-r.width-pad;if(y+r.height>window.innerHeight-8)y=e.clientY-r.height-pad;tip.style.left=x+'px';tip.style.top=y+'px';}
function bindTips(root){if(!root)return;root.addEventListener('mousemove',tipMove,{passive:true});root.addEventListener('mouseover',function(e){const el=e.target&&e.target.closest?e.target.closest('[data-tip]'):null;if(!el)return;const t=el.getAttribute('data-tip');if(t&&t.trim())tipShow(t.trim());});root.addEventListener('mouseout',function(e){const el=e.target&&e.target.closest?e.target.closest('[data-tip]'):null;if(!el)return;const to=e.relatedTarget&&e.relatedTarget.closest?e.relatedTarget.closest('[data-tip]'):null;if(to===el)return;tipHide();});}
bindTips($q('.fight-ui'));
function pct(v,max){return Math.max(0,Math.min(100,Math.floor((v/max)*100)));}
function clamp(n,min,max){return(n<min?min:(n>max?max:n));}
function barColor(percent){if(percent>70)return"#2ecc71";if(percent>35)return"#f1c40f";return"#e74c3c";}
function setActionsEnabled(enabled){['#btn-atk','#btn-heavy','#btn-guard','#btn-heal','#btn-finish'].forEach(sel=>{const b=$q(sel);if(b)b.disabled=!enabled;});}
function setBtnVisible(sel,visible){const b=$q(sel);if(!b)return;b.style.display=visible?'':'none';}
function popNumber(target,text){const layer=$q(target);if(!layer)return;const el=document.createElement('div');el.className='dmg-pop';el.textContent=text;layer.appendChild(el);setTimeout(()=>{try{el.remove();}catch(e){}},700);}
function flashHit(cardSel,barBgSel){const c=$q(cardSel),b=$q(barBgSel);if(c){c.classList.remove('shake');c.classList.add('shake');setTimeout(()=>c.classList.remove('shake'),220);}if(b){b.classList.remove('hitFlash');b.classList.add('hitFlash');setTimeout(()=>b.classList.remove('hitFlash'),260);}}
function nudgeAttack(cardSel){const c=$q(cardSel);if(!c)return;c.classList.remove('attackNudge');c.classList.add('attackNudge');setTimeout(()=>c.classList.remove('attackNudge'),220);}
function showFx(text){const box=$q('#fight-stage');if(!box)return;const el=document.createElement('div');el.className='fxBadge';el.textContent=text;box.prepend(el);setTimeout(()=>{try{el.remove();}catch(e){}},700);}
function renderLog(lines){const box=$q('#fight-stage');if(!box)return;box.innerHTML='';}
function setBottom(wiki){const slot=$q('#fight-actionsbar')||$q('#dealer-actions');if(!slot)return;try{slot.innerHTML='';slot.appendChild(Wikifier.wikifyEval(String(wiki||'')));}catch(e){}}
function pushPopup(title,lines){const box=$q('#fight-popups');if(!box)return;try{box.innerHTML='';const t=String(title||'Info').replace(/"/g,'"');const arr=Array.isArray(lines)?lines:((lines!=null)?[String(lines)]:[]);const html=arr.filter(Boolean).map(s=>String(s)).join('<br>');box.appendChild(Wikifier.wikifyEval('<<InformationUiPopUp "'+t+'">>'+html+'<</InformationUiPopUp>>'));}catch(e){}}
function showReturnButton(){setBottom('<br><<BottomButton "Move">><<link "Return">><<script>>if(State.variables.ReturnTo){SugarCube.Engine.play(String(State.variables.ReturnTo));}else{SugarCube.Engine.backward();}<</script>><</link>><</BottomButton>>');}
function showWakeUpButton(){setBottom('<br><<BottomButton "Action">><<link "Wake up">><<script>>State.variables.Bank=(+State.variables.Bank||0)-200;State.variables.Heal=1;SugarCube.Engine.play("HospitalRoom");<</script>><</link>><</BottomButton>>');}
function applyDotsAndTick(sideKey,log){
const S=(sideKey==='p')?F.p:F.e;
if(S.bleed&&S.bleed>0){const dmg=Math.max(1,+S.bleedDmg||2);if(sideKey==='p'){F.playerHP=Math.max(0,F.playerHP-dmg);popNumber('#you-pop',`-${dmg}`);flashHit('#you-card','#you-barbg');log.push(`🩸 Bleeding tick on you: <strong>-${dmg} HP</strong>.`);}else{F.enemyHP=Math.max(0,F.enemyHP-dmg);popNumber('#foe-pop',`-${dmg}`);flashHit('#foe-card','#foe-barbg');log.push(`🩸 Bleeding tick on enemy: <strong>-${dmg} HP</strong>.`);}S.bleed-=1;}
if(S.guard&&S.guard>0)S.guard-=1;
if(S.exposed&&S.exposed>0)S.exposed-=1;
if(S.adr&&S.adr>0)S.adr-=1;
if(S.stun&&S.stun>0)S.stun-=1;
if(sideKey==='p'){V.Heal=F.playerHP;}
}
function pill(label,tipText){return `<span class="statePill" data-tip="${String(tipText).replace(/"/g,'"')}">${label}</span>`;}
function statePills(S){
let out=[];
if(S.stun>0)out.push(pill(`Stunned ${S.stun}`,"Stunned: skips the next turn."));
if(S.bleed>0)out.push(pill(`Bleeding ${S.bleed}`,"Bleeding: takes damage at the start of each turn."));
if(S.guard>0)out.push(pill("Guarded","Guarded: takes 50% less damage this turn."));
if(S.exposed>0)out.push(pill("Exposed","Exposed: takes 30% more damage."));
if(S.adr>0)out.push(pill("Adrenaline","Adrenaline: your next hit deals 50% more damage."));
return out.join('');
}
function updateHUD(){
const foeType=$q('#foe-type'),foeLvl=$q('#foe-lvl'),foeHP=$q('#foe-hp'),foeMax=$q('#foe-max'),foeBand=$q('#foe-band'),foeBar=$q('#foe-bar'),foeStates=$q('#foe-states');
const youFit=$q('#player-fit'),youHP=$q('#you-hp'),youMax=$q('#you-max'),youBand=$q('#you-band'),youBar=$q('#you-bar'),youStates=$q('#you-states');
const youSta=$q('#you-sta'),youStaTxt=$q('#you-sta-txt');
if(!foeType||!foeLvl||!foeHP||!foeMax||!foeBand||!foeBar||!youFit||!youHP||!youMax||!youBand||!youBar)return;
foeType.textContent=F.type;foeLvl.textContent=F.lvl;foeHP.textContent=F.enemyHP;foeMax.textContent=F.enemyMax;foeBand.textContent=F.enemyBand;
const foePct=pct(F.enemyHP,F.enemyMax);foeBar.style.width=foePct+'%';foeBar.style.background=barColor(foePct);
if(foeStates)foeStates.innerHTML=statePills(F.e);
const fit=Math.max(0,+V.Fitness||0);
youFit.textContent=fit;youHP.textContent=F.playerHP;youMax.textContent=F.playerMax;
const medQty=(V.Inventory&&V.Inventory.medkit&&Number.isFinite(+V.Inventory.medkit.qty))?Math.max(0,+V.Inventory.medkit.qty):0;
youBand.textContent=medQty;
const youPct=pct(F.playerHP,F.playerMax);youBar.style.width=youPct+'%';youBar.style.background=barColor(youPct);
if(youStates)youStates.innerHTML=statePills(F.p);
const staPct=pct(F.playerSta,F.playerStaMax);
if(youSta)youSta.style.width=staPct+'%';
if(youStaTxt)youStaTxt.textContent=`${F.playerSta}/${F.playerStaMax}`;
setBtnVisible('#btn-finish',(F.enemyHP>0&&(F.enemyHP/F.enemyMax)<=0.15));
const healBtn=$q('#btn-heal');
if(healBtn)healBtn.textContent=(F.healCD>0)?'🩹 Heal (CD)':'🩹 Heal';
}
function victoryScreen(){const box=$q('#fight-stage');if(!box)return;setActionsEnabled(false);box.innerHTML='';pushPopup("Victory",["🏆 Victory! The enemy is defeated."]);showReturnButton();}
function defeatScreen(){const box=$q('#fight-stage');if(!box)return;setActionsEnabled(false);box.innerHTML='';pushPopup("Defeat",["💥 You are knocked out.","<em>You will be taken to the hospital and must pay <strong>$200</strong>.</em>"]);showWakeUpButton();}
function endCheck(){if(F.playerHP<=0){defeatScreen();return true;}if(F.enemyHP<=0){victoryScreen();return true;}return false;}
function atkBaseFrom(fit){
const base=Math.floor(Math.random()*6)+6;
const bonus=Math.floor(fit/4);
return base+bonus;
}
function enemyDodgeChance(){
let base=clamp(0.25+(Math.max(1,+F.lvl||1)/400),0.25,0.75);
base=clamp(base+((+F.enemyDodgeBias||0.5)-0.5)*0.25,0.15,0.85);
if(F.e.exposed>0)base=base*0.50;
return clamp(base,0.10,0.90);
}
function playerDodgeChance(fit){
return clamp(0.10+(fit/200),0.10,0.60);
}
function regenCooldownOnly(){if(F.healCD>0)F.healCD-=1;}
function startTurnTick(log){applyDotsAndTick('p',log);applyDotsAndTick('e',log);regenCooldownOnly();}
function enemyActs(log){
if(F.e.stun>0){log.push("😵 Enemy is stunned and skips the turn.");return;}
let action='atk';
const hpPct=F.enemyHP/F.enemyMax;
const roll=Math.random();
if(hpPct<=0.25&&F.enemyBand>0)action='heal';
else if(roll<0.20)action='guard';
else if(roll<0.40)action='heavy';
else action='atk';
if(action==='heal'){const h=Math.floor(F.enemyMax*(0.28+Math.random()*0.04));F.enemyHP=Math.min(F.enemyMax,F.enemyHP+h);F.enemyBand=Math.max(0,(+F.enemyBand||0)-1);showFx("Heal!");log.push(`🩹 Enemy heals: <strong>+${h} HP</strong>.`);return;}
if(action==='guard'){showFx("Guard!");F.e.guard=1;log.push("🛡️ Enemy takes a guarded stance.");return;}
const eFit=Math.max(0,+F.lvl||0);
let dmg=atkBaseFrom(eFit);
if(action==='heavy'){dmg=Math.floor(dmg*2.5);const dChance=enemyDodgeChance();if(Math.random()<dChance){log.push("🛡️ Enemy's heavy blow misses.");return;}showFx("Heavy!");log.push("💥 Enemy goes for a heavy blow!");}else{showFx("Attack!");}
if(F.p.guard>0)dmg=Math.floor(dmg*0.50);
if(F.p.exposed>0)dmg=Math.floor(dmg*1.30);
const fit=Math.max(0,+V.Fitness||0);
const pDodge=playerDodgeChance(fit);
if(action!=='heavy'&&Math.random()<pDodge){showFx("Evade!");log.push("🟦 You evade the enemy hit.");return;}
F.playerHP=Math.max(0,F.playerHP-dmg);
popNumber('#you-pop',`-${dmg}`);
flashHit('#you-card','#you-barbg');
log.push(`🔻 Enemy hits you: <strong>-${dmg} HP</strong>.`);
}
function spendSta(cost){if((+F.playerSta||0)<cost)return false;F.playerSta-=cost;return true;}
function doPlayerAttack(mode){
const fit=Math.max(0,+V.Fitness||0);
let log=[];
let cost=1;
if(mode==='heavy')cost=2;
if(mode==='heal')cost=2;
if(mode==='finish')cost=1;
if(mode==='guard')cost=0;
if(cost>0&&!spendSta(cost)){log.push("⚠️ Not enough stamina.");pushPopup("Fight",log);F.log=log;renderLog(F.log);updateHUD();return;}
if(mode==='guard')F.playerSta=clamp((+F.playerSta||0)+1,0,F.playerStaMax);
if(shouldPunch(mode))playPunchSfx();
startTurnTick(log);
if(endCheck()){updateHUD();return;}
if(mode==='guard'){showFx("Guard!");log.push("🛡️ You take a guarded stance. 50% less damage this turn.");F.p.guard=1;enemyActs(log);F.log=log;pushPopup("Fight",log);renderLog(F.log);updateHUD();endCheck();return;}
if(mode==='heal'){
if(F.healCD>0){log.push("⏳ Heal is on cooldown.");F.log=log;pushPopup("Fight",log);renderLog(F.log);updateHUD();return;}
const med=(V.Inventory&&V.Inventory.medkit)?V.Inventory.medkit:null;
const medQty=(med&&Number.isFinite(+med.qty))?Math.max(0,+med.qty):0;
if(medQty<=0){log.push("❌ You don't have a Medkit.");F.log=log;pushPopup("Fight",log);renderLog(F.log);updateHUD();return;}
V.Inventory.medkit.qty=Math.max(0,medQty-1);
const heal=Math.floor(F.playerMax*(0.28+Math.random()*0.04));
F.playerHP=Math.min(F.playerMax,F.playerHP+heal);
F.healCD=1;showFx("Heal!");log.push(`🩹 You heal: <strong>+${heal} HP</strong>.`);
enemyActs(log);F.log=log;pushPopup("Fight",log);renderLog(F.log);updateHUD();endCheck();return;
}
if(mode==='finish'){
if((F.enemyHP/F.enemyMax)>0.15){log.push("☠️ Finisher not available yet.");F.log=log;pushPopup("Fight",log);renderLog(F.log);updateHUD();return;}
showFx("Finisher!");log.push("☠️ You execute a brutal finisher!");F.enemyHP=0;popNumber('#foe-pop','KO');flashHit('#foe-card','#foe-barbg');F.log=log;pushPopup("Fight",log);renderLog(F.log);updateHUD();endCheck();return;
}
nudgeAttack('#you-card');
let dmg=atkBaseFrom(fit);
if(mode==='heavy'){
dmg=Math.floor(dmg*2.5);
showFx("Heavy!");
log.push("💥 Heavy attack.");
const dChance=enemyDodgeChance();
if(Math.random()<dChance){showFx("Evaded!");log.push("🛡️ Enemy dodges the heavy blow. You lose your turn.");F.log=log;pushPopup("Fight",log);renderLog(F.log);enemyActs(log);updateHUD();endCheck();return;}
if(F.p.adr>0){dmg=Math.floor(dmg*1.50);F.p.adr=0;log.push("⚡ Adrenaline boosts your strike.");}
if(F.e.exposed>0)dmg=Math.floor(dmg*1.30);
if(F.e.guard>0)dmg=Math.floor(dmg*0.50);
F.enemyHP=Math.max(0,F.enemyHP-dmg);
popNumber('#foe-pop',`-${dmg}`);
flashHit('#foe-card','#foe-barbg');
F.p.adr=1;
log.push(`🔺 Heavy hit lands: <strong>-${dmg} HP</strong>. Adrenaline builds.`);
} else {
showFx("Attack!");
log.push("🥊 Standard attack.");
if(F.p.adr>0){dmg=Math.floor(dmg*1.50);F.p.adr=0;log.push("⚡ Adrenaline boosts your strike.");}
if(F.e.exposed>0)dmg=Math.floor(dmg*1.30);
if(F.e.guard>0)dmg=Math.floor(dmg*0.50);
const dChance=enemyDodgeChance();
if(Math.random()<dChance){const reduced=Math.floor(dmg*0.40);F.enemyHP=Math.max(0,F.enemyHP-reduced);popNumber('#foe-pop',`-${reduced}`);if(reduced>0)flashHit('#foe-card','#foe-barbg');log.push(`🛡️ Enemy partially dodges. Damage reduced to <strong>-${reduced} HP</strong>.`);}
else{F.enemyHP=Math.max(0,F.enemyHP-dmg);popNumber('#foe-pop',`-${dmg}`);flashHit('#foe-card','#foe-barbg');log.push(`🔺 You hit: <strong>-${dmg} HP</strong>.`);}
}
enemyActs(log);
F.log=log;pushPopup("Fight",log);renderLog(F.log);updateHUD();endCheck();
}
function bind(sel,fn){const b=$q(sel);if(!b)return;const clone=b.cloneNode(true);b.parentNode.replaceChild(clone,b);clone.addEventListener('click',fn);}
bind('#btn-atk',()=>doPlayerAttack('atk'));
bind('#btn-heavy',()=>doPlayerAttack('heavy'));
bind('#btn-guard',()=>doPlayerAttack('guard'));
bind('#btn-heal',()=>doPlayerAttack('heal'));
bind('#btn-finish',()=>doPlayerAttack('finish'));
setBottom('');
pushPopup("Fight",["Choose an action."]);
updateHUD();
renderLog([]);
});
})();
<</script>><<sound "music" "music.music" true>><<sound "bg" "bg.empty" true>><<passagebg>><<if $Time !== 3>><img src="assets/img/misc/hospital/hospitalroom.webp"/><<else>><img src="assets/img/misc/hospital/hospitalroomnight.webp"/><</if>><</passagebg>>
<<imgcorruption hospital>>
<div class="BottomUiBarCustom">
<<BottomButton "Move">>[[🏥 Reception|Hospital]]<</BottomButton>>
</div><<sound "music" "music.music" true>><<passagebg>><<if $Time !== 3>><<sound "bg" "bg.police" true>><img src="assets/img/misc/police/police.webp"/><<else>><<sound "bg" "bg.empty" true>><img src="assets/img/misc/police/policenight.webp"/><</if>><</passagebg>>
<div class="BottomUiBarCustom">
<<BottomButton "Move">>[[⛓️ Cell|PoliceCell]]
<<link "🏙️ City Center">><<goto "City">><<set $TravelPerTime++>><</link>><</BottomButton>>
</div><<sound "music" "music.music" true>><<passagebg>><<if $Time !== 3>><<sound "bg" "bg.hospital" true>><img src="assets/img/misc/hospital/hospital.webp"/><<else>><<sound "bg" "bg.empty" true>><img src="assets/img/misc/hospital/hospitalnight.webp"/><</if>><</passagebg>><<set _m=$HospitalMarket&&$HospitalMarket[0]? $HospitalMarket[0] : {id:"Medkit",name:"Medkit",price:50}>><<set _id=String(_m.id||"Medkit")>><<set _invKey=_id.toLowerCase()>><<set _qty=($Inventory[_invKey]&&$Inventory[_invKey].qty)?+$Inventory[_invKey].qty:0>><style>
.shp-wrap{display:flex;flex-direction:column;gap:14px;padding:4px 2px;}
.shp-topbar{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;padding:clamp(8px,2vw,12px) clamp(10px,2vw,16px);border-radius:14px;background:rgba(0,0,0,.45);border:1px solid rgba(255,255,255,.10);}
.shp-topbar-title{font-size:calc(24px + var(--font-boost,0px));font-weight:950;color:rgba(255,255,255,.96);letter-spacing:-.01em;}
.shp-balances{display:flex;gap:10px;flex-wrap:wrap;}
.shp-bal{display:flex;flex-direction:column;align-items:flex-end;gap:2px;padding:8px 14px;border-radius:10px;background:rgba(0,0,0,.45);border:1px solid rgba(255,255,255,.10);}
.shp-bal-label{font-size:calc(14px + var(--font-boost,0px));font-weight:900;letter-spacing:.12em;text-transform:uppercase;color:rgba(255,255,255,.65);}
.shp-bal-value{font-size:calc(16px + var(--font-boost,0px));font-weight:950;color:rgba(255,255,255,.96);letter-spacing:-.01em;}
.shp-grid{display:grid;grid-template-columns:repeat(auto-fill, minmax(clamp(140px,15vw,170px), 1fr));gap:10px;}
.shp-card{display:flex;flex-direction:column;border-radius:14px;background:rgba(0,0,0,.45);border:1px solid rgba(255,255,255,.10);overflow:hidden;transition:border-color .14s, background .14s, transform .14s;}
.shp-card:hover{border-color:rgba(255,255,255,.20);background:rgba(0,0,0,.35);transform:translateY(-2px);}
.shp-card-img-wrap{width:100%;aspect-ratio:1;background:#f0f0f0;display:flex;align-items:center;justify-content:center;line-height:0;font-size:0;}
.shp-card-img-wrap img{width:100%!important;height:100%!important;min-width:unset!important;max-width:unset!important;min-height:unset!important;max-height:unset!important;object-fit:contain!important;display:block!important;margin:0!important;}
.shp-card-body{display:flex;flex-direction:column;gap:6px;padding:clamp(8px,2vw,10px) clamp(8px,2vw,10px) clamp(10px,2vw,12px);flex:1 1 auto;}
.shp-card-name{font-size:calc(15px + var(--font-boost,0px));font-weight:950;color:rgba(255,255,255,.96);letter-spacing:.01em;line-height:1.2;}
.shp-card-desc{font-size:calc(14px + var(--font-boost,0px));color:rgba(255,255,255,.75);font-weight:600;line-height:1.35;flex:1 1 auto;}
.shp-card-price{font-size:calc(16px + var(--font-boost,0px));font-weight:950;color:#e65763;letter-spacing:-.01em;}
.shp-card-stock{font-size:calc(14px + var(--font-boost,0px));font-weight:800;color:rgba(255,255,255,.70);letter-spacing:.04em;}
.shp-card-actions{margin-top:4px;}
.shp-card-actions button.link-internal{all:unset;display:block;width:100%;padding:8px 0;border-radius:9px;border:1px solid rgba(230,87,99,.40);background:rgba(230,87,99,.14);color:rgba(230,87,99,.98);font-weight:950;font-size:calc(14px + var(--font-boost,0px));letter-spacing:.08em;text-align:center;cursor:pointer;transition:background .12s, border-color .12s;box-sizing:border-box;}
.shp-card-actions button.link-internal:hover{background:rgba(230,87,99,.24);border-color:rgba(230,87,99,.60);}
.shp-btn-disabled{opacity:.45;pointer-events:none;display:block;width:100%;padding:8px 0;border-radius:9px;border:1px solid rgba(255,255,255,.15);background:rgba(0,0,0,.40);color:rgba(255,255,255,.60);font-weight:950;font-size:calc(14px + var(--font-boost,0px));letter-spacing:.08em;text-align:center;box-sizing:border-box;}
</style><div class="shp-wrap"><div class="shp-topbar"><div><div class="shp-topbar-title">Hospital</div></div><div class="shp-balances"><div class="shp-bal"><div class="shp-bal-label">Money</div><div class="shp-bal-value">$<<=$Money>></div></div><div class="shp-bal"><div class="shp-bal-label">Bank</div><div class="shp-bal-value">$<<=$Bank>></div></div></div></div><div class="shp-grid"><div class="shp-card"><div class="shp-card-img-wrap"><<if _m.img and _m.img !== "">><<= '<img src="'+_m.img+'" alt="Medkit">'>><<else>><span style="font-size:28px;">🩺</span><</if>></div><div class="shp-card-body"><div class="shp-card-name">Medkit</div><div class="shp-card-desc">Restore health on the go.</div><div class="shp-card-stock"><<print _qty>> / 3 owned</div><div class="shp-card-price">$25</div><div class="shp-card-actions"><<if _qty >= 3>><div class="shp-btn-disabled">MAX</div><<else>><<button "BUY">><<if $Money>=25>><<set $Money-=25>><<elseif $Bank>=25>><<set $Bank-=25>><</if>><<if !$Inventory[_invKey]>><<set $Inventory[_invKey]={id:_id,name:_m.name||"Medkit",qty:0,img:_m.img||"",desc:_m.desc||""}>><<elseif !$Inventory[_invKey].desc and _m.desc>><<set $Inventory[_invKey].desc=_m.desc>><</if>><<set $Inventory[_invKey].qty=(+$Inventory[_invKey].qty||0)+1>><<Refresh>><</button>><</if>></div></div></div><div class="shp-card"><div class="shp-card-img-wrap"><span style="font-size:100px;">🏥</span></div><div class="shp-card-body"><div class="shp-card-name">Treatment</div><div class="shp-card-desc">Full health restoration at the clinic. (Only payable via the bank.)</div><div class="shp-card-stock"><<print $Heal>> / <<print $HealMax>> Health</div><div class="shp-card-price">$200</div><div class="shp-card-actions"><<if $Heal == $HealMax>><div class="shp-btn-disabled">FULL</div><<else>><<button "TREAT">><<if $Bank>=200>><<set $Bank-=200>><<set $Heal=100>><</if>><<Refresh>><</button>><</if>></div></div></div></div></div>
<<imgcorruption hospital>>
<div class="BottomUiBarCustom">
<<BottomButton "Move">>[[🛏️ Hospital room|HospitalRoom]]
<<link "🏙️ City Center">><<goto "City">><<set $TravelPerTime++>><</link>><</BottomButton>>
</div><<sound "music" "music.music" true>><<sound "bg" "bg.empty" true>><<passagebg>><img src="assets/img/misc/oldtown/thepit/door.webp"/><</passagebg>><<if $Reputation < 75>><<TalkRandom "Doorman" "assets/img/character/npc/b2.jpg" "Who are you?">>
<<TalkMC "Ah, uh... I just wanted to see what was inside...">>
<<TalkRandom "Doorman" "assets/img/character/npc/b2.jpg" "That's not going to be possible, get out of here.">><br><<if $TalkDealer1 == true>><span id="bribeBlock1"></span><</if>><<elseif $Reputation >= 75 & $TalkDealer2 == false>><<TalkRandom "Doorman" "assets/img/character/npc/b2.jpg" "Who are you?">>
<<TalkMC "Ah, uh... I just wanted to see what was inside...">>
<<TalkRandom "Doorman" "assets/img/character/npc/b2.jpg" "That's not going to be possible, get out of here.">><br><<if $TalkDealer1 == true>><span id="bribeBlock2"></span><</if>><<else>><<TalkMC "Hi, can I come in?">>
<<TalkRandom "Doorman" "assets/img/character/npc/b2.jpg" "Mmh... Go ahead, you can come in.">><</if>>
<div class="BottomUiBarCustom"><<if $Reputation < 75>><<if $TalkDealer1 == true>><span id="action1"><<BottomButton "Action">><<link "Bribe">><<if $Money>=50>><<set $Money-=50>><<set _Bribe = true>><<replace "#bribeBlock1">><span style="opacity:.85;"><em>(You discreetly slip 50$.)</em></span><br><em>The guard steps aside and lets you pass.</em><br><<TalkRandom "Doorman" "assets/img/character/npc/b2.jpg" "Mmh... Go ahead.">><</replace>><<replace "#entrance1">><<link "➡️ Entrance">><<goto "ThePit">><</link>><</replace>><<replace "#action1">><</replace>><<else>><<replace "#bribeBlock1">><span style="color:#ff6b6b;"><em>You don’t have enough money (50$ required).</em></span><</replace>><</if>><</link>><</BottomButton>></span><<BottomButton "Move">><span id="entrance1">[[🚪 Exit|Oldtown]]</span><</BottomButton>><</if>>
<<elseif $Reputation >= 75 & $TalkDealer2 == false>><<if $TalkDealer1 == true>><span id="action2"><<BottomButton "Action">><<link "Bribe">><<replace "#bribeBlock2">><em>As I started to pull out a 50$ bill, the guard spoke again.</em><br><<TalkRandom "Doorman" "assets/img/character/npc/b2.jpg" "Oh, it’s you, W. I didn’t recognize you. Go ahead, you can enter.">><br><em>Behind me was the dealer who had advised me to come fight here.</em><br><<TalkRandom "W. <em>(Dealer)</em>" "assets/img/character/npc/b3.jpg" "Wait a second… you look familiar.">>
<<TalkMC "Yes. I went into your building to ask you for work, to make some money. And you told me to come fight here, at ThePit.">>
<<TalkRandom "W. <em>(Dealer)</em>" "assets/img/character/npc/b3.jpg" "Fuck, so it was you...">>
<<TalkRandom "W. <em>(Dealer)</em>" "assets/img/character/npc/b3.jpg" "Go on, let him pass, he’s with me.">>
<<TalkRandom "Doorman" "assets/img/character/npc/b2.jpg" "Ok, go ahead.">><</replace>><<replace "#entrance2">><<link "➡️ Entrance">><<set $TalkDealer2 = true>><<goto "ThePit">><</link>><</replace>><<replace "#action2">><</replace>><</link>><</BottomButton>></span><<BottomButton "Move">><span id="entrance2">[[🚪 Exit|Oldtown]]</span><</BottomButton>><</if>>
<<else>><<BottomButton "Move">><<link "➡️ Entrance">><<goto "ThePit">><</link>>
[[🚪 Exit|Oldtown]]<</BottomButton>><</if>>
</div><<sound "music" "music.music" true>><<sound "bg" "bg.empty" true>><<passagebg>><<if $Time !== 3>><img src="assets/img/misc/oldtown/traphouse/traphouse.webp"/><<else>><img src="assets/img/misc/oldtown/traphouse/traphousenight.webp"/><</if>><</passagebg>><<InformationUiPopUp "Traphouse">><em>You enter a run-down building after seeing several people come out of it with stacks of cash in their hands. Walking down a narrow hallway, you reach a dark and dirty room where a few guys are sitting, watching the place.</em>
<em>Suddenly, one of them calls out to you.</em>
<</InformationUiPopUp>>
<<TalkRandom "Dealer" "assets/img/character/npc/b3.jpg" "Who the hell are you? Get out of here!">>
<<TalkMC "Whoa, whoa! Wait, wait… I’m not here to cause trouble, I wa-">>
<<TalkRandom "Dealer" "assets/img/character/npc/b3.jpg" "What the hell are you doing here then, you son of a bitch?!">>
<<TalkMC "I saw some guys walk out of here with a lot of cash, I saw some guys walk out of here with a lot of cash, so I just followed the trail. I’m looking to make money… I could work for you, right?">>
<<TalkRandom "Dealer" "assets/img/character/npc/b3.jpg" "Who do you think you are, barging in like this? You really think I’m going to calmly tell you we’ve got tons of illegal stuff? Don’t be stupid… for all I know, you’re a fucking cop.">>
<<TalkMC "No, no… I’m just looking for a way to make money, that’s all.">>
<<TalkRandom "Dealer" "assets/img/character/npc/b3.jpg" "Just by looking at you, it’s obvious you’ve got zero experience, you’ve clearly never fought before. Go do a few fights first, then we’ll see later if you’ve still got the balls to come back here.">>
<<TalkMC "Is there a place where I could do that?">>
<<TalkRandom "Dealer" "assets/img/character/npc/b3.jpg" "Go to <strong>ThePit</strong>, that’s the best place for it.">>
<<TalkMC "Ok, got it.">>
<div class="BottomUiBarCustom">
<<BottomButton "Story">><<link "➡️ Exit">><<goto "TrapHouse">><<set $TalkDealer1 = true>><</link>><</BottomButton>>
</div><<sound "music" "music.fight" true>><<sound "bg" "bg.thepit" true>><<passagebg>><img src="assets/img/misc/oldtown/thepit/thepit.webp"/><</passagebg>><<InformationUiPopUp>>
<<PitEnterFight>>
<<PitBetting>>
<<PitScoreboard>>
<</InformationUiPopUp>>
<div class="BottomUiBarCustom">
<<BottomButton "Move">>[[🚪 Exit|Oldtown]]<</BottomButton>>
</div><<sound "music" "music.fight" true>><<sound "bg" "bg.thepit" true>><<passagebg>><img src="assets/img/misc/oldtown/thepit/fight.webp"/><</passagebg>><div id="fight-tip" style="display:none;"></div><div class="fight-ui" style="max-width:960px;margin:auto;"><div id="foe-card" class="foes card" style="display:flex;gap:12px;justify-content:space-between;align-items:center;padding:10px;border:1px solid #444;border-radius:10px;margin-bottom:10px;"><div style="width:100%;"><p style="margin:0;"><strong>Enemy:</strong> <span id="foe-type"></span> (Lv <span id="foe-lvl"></span>) <span id="foe-states" class="states"></span></p><div class="hp-bar-bg" id="foe-barbg"><div id="foe-bar" class="hp-bar"></div><div class="pop-layer" id="foe-pop"></div></div><p style="margin:4px 0 0 0;">HP <span id="foe-hp"></span> / <span id="foe-max"></span> · 🩹 <span id="foe-band"></span></p></div></div><div id="you-card" class="you card" style="display:flex;gap:12px;justify-content:space-between;align-items:center;padding:10px;border:1px solid #444;border-radius:10px;margin-bottom:14px;"><div style="width:100%;"><p style="margin:0;"><strong>You</strong> (Fitness <span id="player-fit"></span>) <span id="you-states" class="states"></span></p><div class="hp-bar-bg" id="you-barbg"><div id="you-bar" class="hp-bar"></div><div class="pop-layer" id="you-pop"></div></div><div class="sta-row"><span class="sta-label">Stamina</span><div class="sta-bg"><div id="you-sta" class="sta-bar"></div></div><span id="you-sta-txt" class="sta-txt"></span></div><p style="margin:4px 0 0 0;">HP <span id="you-hp"></span> / <span id="you-max"></span> · 🩹 <span id="you-band"></span></p></div></div><div id="fight-actions" style="display:flex;gap:10px;flex-wrap:wrap;margin-bottom:10px;"><button id="btn-atk" type="button" data-tip="Standard attack. Deals solid damage based on your Fitness. Cost: 1 stamina.">🥊 Attack</button><button id="btn-heavy" type="button" data-tip="Heavy attack. Deals 2.5x damage based on Fitness, but costs 2 stamina and misses more often.">💥 Heavy</button><button id="btn-guard" type="button" data-tip="Guard. You take 50% less damage this turn. Cost: 0 stamina. Gain: +1 stamina.">🛡️ Guard</button><button id="btn-heal" type="button" data-tip="Heal using a Medkit. Cooldown: every other turn. Cost: 2 stamina. Requires: 1 Medkit.">🩹 Heal</button><button id="btn-finish" type="button" style="display:none;" data-tip="Finisher. Available when enemy HP is 15% or less. Ends the fight instantly. Cost: 1 stamina.">☠️ Finisher</button></div><div id="fight-popups"></div><div id="fight-stage"></div></div><div class="BottomUiBarCustom"><span style="display: contents;" id="fight-actionsbar"></span></div><style>#fight-tip{position:fixed;z-index:99999;display:none;max-width:280px;padding:8px 10px;border:1px solid rgba(255,255,255,.25);border-radius:10px;background:rgba(10,10,10,.92);backdrop-filter:blur(3px);color:#fff;font-size:.9rem;line-height:1.25;pointer-events:none;box-shadow:0 6px 18px rgba(0,0,0,.35);} .fight-ui p{line-height:1.3;} .fight-ui .card{background:rgba(255,255,255,0.03);} #fight-actions button{padding:8px 12px;border:1px solid #666;border-radius:8px;background:transparent;cursor:pointer;color: #fff;} #fight-actions button:hover{background:rgba(255,255,255,0.06);} #fight-actions button:disabled{opacity:.45;cursor:not-allowed;} .hp-bar-bg{position:relative;height:14px;background:#222;border-radius:7px;overflow:hidden;margin-top:6px;} .hp-bar{height:100%;width:100%;transition:width 250ms ease-in-out,background 250ms linear;} .pop-layer{position:absolute;inset:0;pointer-events:none;overflow:visible;} .dmg-pop{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);font-weight:800;opacity:0;animation:popFloat 650ms ease-out forwards;text-shadow:0 1px 0 rgba(0,0,0,.55);} @keyframes popFloat{0%{opacity:0;transform:translate(-50%,-40%) scale(.9);}15%{opacity:1;}100%{opacity:0;transform:translate(-50%,-140%) scale(1.05);}} .hitFlash{animation:hitFlash 220ms ease-out;} @keyframes hitFlash{0%{filter:none;}40%{filter:brightness(1.35);}100%{filter:none;}} .shake{animation:shake 180ms ease-in-out;} @keyframes shake{0%{transform:translateX(0);}25%{transform:translateX(-3px);}50%{transform:translateX(3px);}75%{transform:translateX(-2px);}100%{transform:translateX(0);}} .attackNudge{animation:attackNudge 160ms ease-in-out;} @keyframes attackNudge{0%{transform:translateX(0);}50%{transform:translateX(3px);}100%{transform:translateX(0);}} .states{font-size:.85rem;opacity:.9;margin-left:8px;} .statePill{display:inline-block;padding:1px 6px;border:1px solid rgba(255,255,255,.25);border-radius:999px;margin-left:6px;font-size:.78rem;} .sta-row{display:flex;align-items:center;gap:8px;margin-top:8px;} .sta-label{font-size:.85rem;opacity:.9;} .sta-bg{height:10px;width:160px;border-radius:6px;background:#222;overflow:hidden;} .sta-bar{height:100%;width:100%;transition:width 200ms ease-in-out;background:#5090e2;} .sta-txt{font-size:.85rem;opacity:.9;min-width:34px;text-align:right;} .fxBadge{display:inline-block;margin-top:6px;font-weight:900;letter-spacing:.3px;opacity:0;animation:fxBadge 650ms ease-out forwards;} @keyframes fxBadge{0%{opacity:0;transform:translateY(2px) scale(.98);}20%{opacity:1;}100%{opacity:0;transform:translateY(-10px) scale(1.02);}}</style>
<<script>>
(function(){
$(document).on(':passagedisplay', function(ev){
if(!ev||!ev.passage||ev.passage.title!=='FightThePit')return;
const V=State.variables;
const F=V.Fight||(V.Fight={type:"?",lvl:1,playerMax:100,enemyMax:100,playerHP:100,enemyHP:100,playerBand:0,enemyBand:1,playerStaMax:5,playerSta:5,healCD:0,log:[],p:{},e:{}});
const $q=(sel)=>document.querySelector(sel);
function playPunchSfx(){try{if(!window.setup||!setup.AudioMixer)return;setup.AudioMixer.playPlaylist("sfx","sfx.punch",false,{fadeInMs:0,fadeOutMs:0});}catch(e){}}
function shouldPunch(mode){return mode==='atk'||mode==='heavy'||mode==='finish';}
const tip=$q('#fight-tip');
function tipShow(text){if(!tip)return;tip.textContent=text;tip.style.display='block';}
function tipHide(){if(!tip)return;tip.style.display='none';}
function tipMove(e){if(!tip||tip.style.display==='none')return;const pad=14;let x=e.clientX+pad,y=e.clientY+pad;const r=tip.getBoundingClientRect();if(x+r.width>window.innerWidth-8)x=e.clientX-r.width-pad;if(y+r.height>window.innerHeight-8)y=e.clientY-r.height-pad;tip.style.left=x+'px';tip.style.top=y+'px';}
function bindTips(root){if(!root)return;root.addEventListener('mousemove',tipMove,{passive:true});root.addEventListener('mouseover',function(e){const el=e.target&&e.target.closest?e.target.closest('[data-tip]'):null;if(!el)return;const t=el.getAttribute('data-tip');if(t&&t.trim())tipShow(t.trim());});root.addEventListener('mouseout',function(e){const el=e.target&&e.target.closest?e.target.closest('[data-tip]'):null;if(!el)return;const to=e.relatedTarget&&e.relatedTarget.closest?e.relatedTarget.closest('[data-tip]'):null;if(to===el)return;tipHide();});}
bindTips($q('.fight-ui'));
function pct(v,max){return Math.max(0,Math.min(100,Math.floor((v/max)*100)));}
function clamp(n,min,max){return(n<min?min:(n>max?max:n));}
function barColor(percent){if(percent>70)return"#2ecc71";if(percent>35)return"#f1c40f";return"#e74c3c";}
function setActionsEnabled(enabled){['#btn-atk','#btn-heavy','#btn-guard','#btn-heal','#btn-finish'].forEach(sel=>{const b=$q(sel);if(b)b.disabled=!enabled;});}
function setBtnVisible(sel,visible){const b=$q(sel);if(!b)return;b.style.display=visible?'':'none';}
function popNumber(target,text){const layer=$q(target);if(!layer)return;const el=document.createElement('div');el.className='dmg-pop';el.textContent=text;layer.appendChild(el);setTimeout(()=>{try{el.remove();}catch(e){}},700);}
function flashHit(cardSel,barBgSel){const c=$q(cardSel),b=$q(barBgSel);if(c){c.classList.remove('shake');c.classList.add('shake');setTimeout(()=>c.classList.remove('shake'),220);}if(b){b.classList.remove('hitFlash');b.classList.add('hitFlash');setTimeout(()=>b.classList.remove('hitFlash'),260);}}
function nudgeAttack(cardSel){const c=$q(cardSel);if(!c)return;c.classList.remove('attackNudge');c.classList.add('attackNudge');setTimeout(()=>c.classList.remove('attackNudge'),220);}
function showFx(text){const box=$q('#fight-stage');if(!box)return;const el=document.createElement('div');el.className='fxBadge';el.textContent=text;box.prepend(el);setTimeout(()=>{try{el.remove();}catch(e){}},700);}
function renderLog(lines){const box=$q('#fight-stage');if(!box)return;box.innerHTML='';}
function setBottom(wiki){const slot=$q('#fight-actionsbar')||$q('#dealer-actions');if(!slot)return;try{slot.innerHTML='';slot.appendChild(Wikifier.wikifyEval(String(wiki||'')));}catch(e){}}
function pushPopup(title,lines){const box=$q('#fight-popups');if(!box)return;try{box.innerHTML='';const t=String(title||'Info').replace(/"/g,'"');const arr=Array.isArray(lines)?lines:((lines!=null)?[String(lines)]:[]);const html=arr.filter(Boolean).map(s=>String(s)).join('<br>');box.appendChild(Wikifier.wikifyEval('<<InformationUiPopUp "'+t+'">>'+html+'<</InformationUiPopUp>>'));}catch(e){}}
function pitExitButton(){setBottom('<br><<BottomButton "Move">><<link "Back to The Pit">><<script>>SugarCube.Engine.play("ThePit");<</script>><</link>><</BottomButton>>');}
function applyPitResultOnce(playerWon){try{if(V.PitFight&&V.PitFight.processed)return;if(setup&&setup.pit&&typeof setup.pit.finishPlayerPitFight==='function'){setup.pit.finishPlayerPitFight(!!playerWon);}else if(setup&&setup.pit&&typeof setup.pit.onFightEnd==='function'){setup.pit.onFightEnd(!!playerWon);}}catch(e){}}
function victoryScreenPit(){const box=$q('#fight-stage');if(!box)return;setActionsEnabled(false);box.innerHTML='';applyPitResultOnce(true);V.Reputation=Math.max(0,Math.floor((+V.Reputation||0)+5));const last=V.PitLastPitResult||{payout:0,eloDelta:0,newElo:0};pushPopup("Victory",["🏆 Victory! You win the pit fight.","<strong>Reputation:</strong> +5 • <strong>Payout:</strong> $"+Math.max(0,Math.floor(+last.payout||0))+" • <strong>Elo:</strong> "+(last.eloDelta>=0?'+':'')+Math.round(+last.eloDelta||0)+" (now "+Math.round(+last.newElo||0)+")"]);State.variables.Ach_Counter_Elo=Math.round(+last.newElo||0);pitExitButton();}
function defeatScreenPit(){const box=$q('#fight-stage');if(!box)return;setActionsEnabled(false);box.innerHTML='';applyPitResultOnce(false);V.Reputation=Math.max(0,Math.floor((+V.Reputation||0)-5));const last=V.PitLastPitResult||{payout:0,eloDelta:0,newElo:0};pushPopup("Defeat",["💥 Defeat. You lose the pit fight.","<strong>Reputation:</strong> -5 • <strong>HP set to:</strong> 25 • <strong>Elo:</strong> "+(last.eloDelta>=0?'+':'')+Math.round(+last.eloDelta||0)+" (now "+Math.round(+last.newElo||0)+")"]);pitExitButton();}
function endCheck(){if(F.playerHP<=0){defeatScreenPit();return true;}if(F.enemyHP<=0){victoryScreenPit();return true;}return false;}
function applyDotsAndTick(sideKey,log){
const S=(sideKey==='p')?F.p:F.e;
if(S.bleed&&S.bleed>0){const dmg=Math.max(1,+S.bleedDmg||2);if(sideKey==='p'){F.playerHP=Math.max(0,F.playerHP-dmg);popNumber('#you-pop',`-${dmg}`);flashHit('#you-card','#you-barbg');log.push(`🩸 Bleeding tick on you: <strong>-${dmg} HP</strong>.`);}else{F.enemyHP=Math.max(0,F.enemyHP-dmg);popNumber('#foe-pop',`-${dmg}`);flashHit('#foe-card','#foe-barbg');log.push(`🩸 Bleeding tick on enemy: <strong>-${dmg} HP</strong>.`);}S.bleed-=1;}
if(S.guard&&S.guard>0)S.guard-=1;
if(S.exposed&&S.exposed>0)S.exposed-=1;
if(S.adr&&S.adr>0)S.adr-=1;
if(S.stun&&S.stun>0)S.stun-=1;
if(sideKey==='p'){V.Heal=F.playerHP;}
}
function pill(label,tipText){return `<span class="statePill" data-tip="${String(tipText).replace(/"/g,'"')}">${label}</span>`;}
function statePills(S){
let out=[];
if(S.stun>0)out.push(pill(`Stunned ${S.stun}`,"Stunned: skips the next turn."));
if(S.bleed>0)out.push(pill(`Bleeding ${S.bleed}`,"Bleeding: takes damage at the start of each turn."));
if(S.guard>0)out.push(pill("Guarded","Guarded: takes 50% less damage this turn."));
if(S.exposed>0)out.push(pill("Exposed","Exposed: takes 30% more damage."));
if(S.adr>0)out.push(pill("Adrenaline","Adrenaline: your next hit deals 50% more damage."));
return out.join('');
}
function updateHUD(){
const foeType=$q('#foe-type'),foeLvl=$q('#foe-lvl'),foeHP=$q('#foe-hp'),foeMax=$q('#foe-max'),foeBand=$q('#foe-band'),foeBar=$q('#foe-bar'),foeStates=$q('#foe-states');
const youFit=$q('#player-fit'),youHP=$q('#you-hp'),youMax=$q('#you-max'),youBand=$q('#you-band'),youBar=$q('#you-bar'),youStates=$q('#you-states');
const youSta=$q('#you-sta'),youStaTxt=$q('#you-sta-txt');
if(!foeType||!foeLvl||!foeHP||!foeMax||!foeBand||!foeBar||!youFit||!youHP||!youMax||!youBand||!youBar)return;
foeType.textContent=F.type;foeLvl.textContent=F.lvl;foeHP.textContent=F.enemyHP;foeMax.textContent=F.enemyMax;foeBand.textContent=F.enemyBand;
const foePct=pct(F.enemyHP,F.enemyMax);foeBar.style.width=foePct+'%';foeBar.style.background=barColor(foePct);
if(foeStates)foeStates.innerHTML=statePills(F.e);
const fit=Math.max(0,+V.Fitness||0);
youFit.textContent=fit;youHP.textContent=F.playerHP;
const realMax=(Number.isFinite(+V.HealMax))?Math.max(1,Math.floor(+V.HealMax)):Math.max(1,Math.floor(+F.playerMax||1));
F.playerMax=realMax;
youMax.textContent=realMax;
const medQty=(V.Inventory&&V.Inventory.medkit&&Number.isFinite(+V.Inventory.medkit.qty))?Math.max(0,+V.Inventory.medkit.qty):0;
youBand.textContent=medQty;
const youPct=pct(F.playerHP,realMax);youBar.style.width=youPct+'%';youBar.style.background=barColor(youPct);
if(youStates)youStates.innerHTML=statePills(F.p);
const staPct=pct(F.playerSta,F.playerStaMax);
if(youSta)youSta.style.width=staPct+'%';
if(youStaTxt)youStaTxt.textContent=`${F.playerSta}/${F.playerStaMax}`;
setBtnVisible('#btn-finish',(F.enemyHP>0&&(F.enemyHP/F.enemyMax)<=0.15));
const healBtn=$q('#btn-heal');
if(healBtn)healBtn.textContent=(F.healCD>0)?'🩹 Heal (CD)':'🩹 Heal';
}
function atkBaseFrom(fit){const base=Math.floor(Math.random()*6)+6;const bonus=Math.floor(fit/4);return base+bonus;}
function enemyDodgeChance(){
let base=clamp(0.25+(Math.max(1,+F.lvl||1)/400),0.25,0.75);
base=clamp(base+((+F.enemyDodgeBias||0.5)-0.5)*0.25,0.15,0.85);
if(F.e.exposed>0)base=base*0.50;
return clamp(base,0.10,0.90);
}
function playerDodgeChance(fit){return clamp(0.10+(fit/200),0.10,0.60);}
function regenCooldownOnly(){if(F.healCD>0)F.healCD-=1;}
function startTurnTick(log){applyDotsAndTick('p',log);applyDotsAndTick('e',log);regenCooldownOnly();}
function enemyActs(log){
if(F.e.stun>0){log.push("😵 Enemy is stunned and skips the turn.");return;}
const elv=Math.max(1,+F.lvl||1);
let action='atk';
const hpPct=F.enemyHP/F.enemyMax;
const roll=Math.random();
if(hpPct<=0.25&&F.enemyBand>0)action='heal';
else if(roll<0.20)action='guard';
else if(roll<0.40)action='heavy';
else action='atk';
if(action==='heal'){const h=Math.floor(F.enemyMax*(0.28+Math.random()*0.04));F.enemyHP=Math.min(F.enemyMax,F.enemyHP+h);F.enemyBand=Math.max(0,(+F.enemyBand||0)-1);showFx("Heal!");log.push(`🩹 Enemy heals: <strong>+${h} HP</strong>.`);return;}
if(action==='guard'){showFx("Guard!");F.e.guard=1;log.push("🛡️ Enemy takes a guarded stance.");return;}
const eFit=Math.max(0,+F.lvl||0);
let dmg=atkBaseFrom(eFit);
if(action==='heavy'){dmg=Math.floor(dmg*2.5);const dChance=enemyDodgeChance();if(Math.random()<dChance){log.push("🛡️ Enemy's heavy blow misses.");return;}showFx("Heavy!");log.push("💥 Enemy goes for a heavy blow!");}else{showFx("Attack!");}
if(F.p.guard>0)dmg=Math.floor(dmg*0.50);
if(F.p.exposed>0)dmg=Math.floor(dmg*1.30);
const fit=Math.max(0,+V.Fitness||0);
const pDodge=playerDodgeChance(fit);
if(action!=='heavy'&&Math.random()<pDodge){showFx("Evade!");log.push("🟦 You evade the enemy hit.");return;}
F.playerHP=Math.max(0,F.playerHP-dmg);
popNumber('#you-pop',`-${dmg}`);
flashHit('#you-card','#you-barbg');
log.push(`🔻 Enemy hits you: <strong>-${dmg} HP</strong>.`);
}
function spendSta(cost){if((+F.playerSta||0)<cost)return false;F.playerSta-=cost;return true;}
function doPlayerAttack(mode){
const fit=Math.max(0,+V.Fitness||0);
let log=[];
let cost=1;
if(mode==='heavy')cost=2;
if(mode==='heal')cost=2;
if(mode==='finish')cost=1;
if(mode==='guard')cost=0;
if(cost>0&&!spendSta(cost)){log.push("⚠️ Not enough stamina.");pushPopup("Fight",log);F.log=log;renderLog(F.log);updateHUD();return;}
if(mode==='guard')F.playerSta=clamp((+F.playerSta||0)+1,0,F.playerStaMax);
if(shouldPunch(mode))playPunchSfx();
startTurnTick(log);
if(endCheck()){updateHUD();return;}
if(mode==='guard'){showFx("Guard!");log.push("🛡️ You take a guarded stance. 50% less damage this turn.");F.p.guard=1;enemyActs(log);F.log=log;pushPopup("Fight",log);renderLog(F.log);updateHUD();endCheck();return;}
if(mode==='heal'){
if(F.healCD>0){log.push("⏳ Heal is on cooldown.");F.log=log;pushPopup("Fight",log);renderLog(F.log);updateHUD();return;}
const med=(V.Inventory&&V.Inventory.medkit)?V.Inventory.medkit:null;
const medQty=(med&&Number.isFinite(+med.qty))?Math.max(0,+med.qty):0;
if(medQty<=0){log.push("❌ You don't have a Medkit.");F.log=log;pushPopup("Fight",log);renderLog(F.log);updateHUD();return;}
V.Inventory.medkit.qty=Math.max(0,medQty-1);
const heal=Math.floor(F.playerMax*(0.28+Math.random()*0.04));
F.playerHP=Math.min(F.playerMax,F.playerHP+heal);
F.healCD=1;showFx("Heal!");log.push(`🩹 You heal: <strong>+${heal} HP</strong>.`);
enemyActs(log);F.log=log;pushPopup("Fight",log);renderLog(F.log);updateHUD();endCheck();return;
}
if(mode==='finish'){
if((F.enemyHP/F.enemyMax)>0.15){log.push("☠️ Finisher not available yet.");F.log=log;pushPopup("Fight",log);renderLog(F.log);updateHUD();return;}
showFx("Finisher!");log.push("☠️ You execute a brutal finisher!");F.enemyHP=0;popNumber('#foe-pop','KO');flashHit('#foe-card','#foe-barbg');F.log=log;pushPopup("Fight",log);renderLog(F.log);updateHUD();endCheck();return;
}
nudgeAttack('#you-card');
let dmg=atkBaseFrom(fit);
if(mode==='heavy'){
dmg=Math.floor(dmg*2.5);
showFx("Heavy!");
log.push("💥 Heavy attack.");
const dChance=enemyDodgeChance();
if(Math.random()<dChance){showFx("Evaded!");log.push("🛡️ Enemy dodges the heavy blow. You lose your turn.");F.log=log;pushPopup("Fight",log);renderLog(F.log);enemyActs(log);updateHUD();endCheck();return;}
if(F.p.adr>0){dmg=Math.floor(dmg*1.50);F.p.adr=0;log.push("⚡ Adrenaline boosts your strike.");}
if(F.e.exposed>0)dmg=Math.floor(dmg*1.30);
if(F.e.guard>0)dmg=Math.floor(dmg*0.50);
F.enemyHP=Math.max(0,F.enemyHP-dmg);
popNumber('#foe-pop',`-${dmg}`);
flashHit('#foe-card','#foe-barbg');
F.p.adr=1;
log.push(`🔺 Heavy hit lands: <strong>-${dmg} HP</strong>. Adrenaline builds.`);
} else {
showFx("Attack!");
log.push("🥊 Standard attack.");
if(F.p.adr>0){dmg=Math.floor(dmg*1.50);F.p.adr=0;log.push("⚡ Adrenaline boosts your strike.");}
if(F.e.exposed>0)dmg=Math.floor(dmg*1.30);
if(F.e.guard>0)dmg=Math.floor(dmg*0.50);
const dChance=enemyDodgeChance();
if(Math.random()<dChance){const reduced=Math.floor(dmg*0.40);F.enemyHP=Math.max(0,F.enemyHP-reduced);popNumber('#foe-pop',`-${reduced}`);if(reduced>0)flashHit('#foe-card','#foe-barbg');log.push(`🛡️ Enemy partially dodges. Damage reduced to <strong>-${reduced} HP</strong>.`);}
else{F.enemyHP=Math.max(0,F.enemyHP-dmg);popNumber('#foe-pop',`-${dmg}`);flashHit('#foe-card','#foe-barbg');log.push(`🔺 You hit: <strong>-${dmg} HP</strong>.`);}
}
enemyActs(log);
F.log=log;pushPopup("Fight",log);renderLog(F.log);updateHUD();endCheck();
}
function bind(sel,fn){const b=$q(sel);if(!b)return;const clone=b.cloneNode(true);b.parentNode.replaceChild(clone,b);clone.addEventListener('click',fn);}
bind('#btn-atk',()=>doPlayerAttack('atk'));
bind('#btn-heavy',()=>doPlayerAttack('heavy'));
bind('#btn-guard',()=>doPlayerAttack('guard'));
bind('#btn-heal',()=>doPlayerAttack('heal'));
bind('#btn-finish',()=>doPlayerAttack('finish'));
setBottom('');
pushPopup("Fight",["Choose an action."]);
updateHUD();
renderLog([]);
});
})();
<</script>><<sound "music" "music.music" true>><<sound "bg" "bg.empty" true>><<passagebg>><<if $Time !== 3>><img src="assets/img/misc/oldtown/traphouse/traphouse.webp"/><<else>><img src="assets/img/misc/oldtown/traphouse/traphousenight.webp"/><</if>><</passagebg>><<InformationUiPopUp "Traphouse">><em>You enter the run-down building. You go back through the narrow hallway and end up in a dark, filthy room where a few guys are sitting, watching the place.</em>
<em>Suddenly, one of them calls out to you.</em>
<</InformationUiPopUp>>
<<TalkRandom "W. <em>(Dealer)</em>" "assets/img/character/npc/b3.jpg" "Who the hell are you? Move along.">>
<<TalkRandom "W. <em>(Dealer)</em>" "assets/img/character/npc/b3.jpg" "Wait... Damn yeah, it’s you.">>
<<TalkRandom "W. <em>(Dealer)</em>" "assets/img/character/npc/b3.jpg" "Word is you made a name for yourself beating those guys over there. Not bad.">>
<<TalkRandom "W. <em>(Dealer)</em>" "assets/img/character/npc/b3.jpg" "So I guess if you’re here, it’s to make some cash.">>
<<TalkMC "Yeah.">>
<<TalkRandom "W. <em>(Dealer)</em>" "assets/img/character/npc/b3.jpg" "Alright, good. I’ll explain how this is going to work.">>
<<TalkRandom "W. <em>(Dealer)</em>" "assets/img/character/npc/b3.jpg" "You don’t work directly for me. We keep it simple. You buy the stuff from me, then you handle selling it yourself for a small profit.">>
<<TalkMC "And where can I sell it?">>
<<TalkRandom "W. <em>(Dealer)</em>" "assets/img/character/npc/b3.jpg" "Anywhere there are people. Parks, campuses, Oldtown, whatever. Just make sure you don’t get caught by the cops or by rival dealers.">>
<<TalkRandom "W. <em>(Dealer)</em>" "assets/img/character/npc/b3.jpg" "You in?">>
<<TalkMC "Yeah, I’m in.">>
<div class="BottomUiBarCustom">
<<BottomButton "Story">><<link "➡️ Exit">><<goto "TrapHouse">><<set $TalkDealer3 = true>><</link>><</BottomButton>>
</div><<sound "music" "music.club" true>><<passagebg>><img src="assets/img/misc/oldtown/redlight/stripclub/choicestripper.webp"/><</passagebg>><video src="assets/img/misc/oldtown/redlight/stripclub/stripper/1/1.mp4"/>
<<TalkMC "Hey, beautiful, are you new here? You seem to know how to captivate an audience with just one look.">>
<<TalkRandom "Stripper" "assets/img/misc/oldtown/redlight/stripclub/stripper/1/avatar.webp" "Oh, honey, I'm not new, but for you, I can pretend I am. Like what you see? I'm right here in front of you, ready to make you forget all your problems.">>
<video src="assets/img/misc/oldtown/redlight/stripclub/stripper/1/2.mp4"/>
<<TalkMC "Yeah, you're impressive. Come closer, show me what you've got in store for me.">>
<<TalkRandom "Stripper" "assets/img/misc/oldtown/redlight/stripclub/stripper/1/avatar.webp" "With pleasure. Look at me, I'm all yours tonight. What turns you on, tell me?">>
<video src="assets/img/misc/oldtown/redlight/stripclub/stripper/1/3.mp4"/>
<<TalkMC "Wow, those moves... You're a pro at twerking, huh? That gives me some ideas for later.">>
<<TalkRandom "Stripper" "assets/img/misc/oldtown/redlight/stripclub/stripper/1/avatar.webp" "Do you like it when I move like that for you? It's my little secret for turning up the heat. Imagine what I can do if you let me continue.">>
<<TalkMC "Keep going, don't stop. You're getting me hooked on your style.">>
<<TalkRandom "Stripper" "assets/img/misc/oldtown/redlight/stripclub/stripper/1/avatar.webp" "Haha, that's the goal, baby. This twerk is just a taste. Tell me if you want me to speed up or slow down for you.">>
<<TalkMC "Come on, take it to the next level. Take me in your mouth, suck me like an expert.">>
<video src="assets/img/misc/oldtown/redlight/stripclub/stripper/1/4.mp4"/>
<<TalkRandom "Stripper" "assets/img/misc/oldtown/redlight/stripclub/stripper/1/avatar.webp" "Mmm, you like it when I suck you, huh? I'm going to melt you with my tongue. Is that good?">>
<<TalkMC "Fuck, yes, keep sucking. You're so good with your mouth.">>
<<TalkRandom "Stripper" "assets/img/misc/oldtown/redlight/stripclub/stripper/1/avatar.webp" "I know, baby. I'm gonna suck you until you beg for more.">>
<video src="assets/img/misc/oldtown/redlight/stripclub/stripper/1/5.mp4"/>
<<TalkMC "Damn, you're incredible. Get on top of me like that and show me what you've learned.">>
<<TalkRandom "Stripper" "assets/img/misc/oldtown/redlight/stripclub/stripper/1/avatar.webp" "Mmm, you like seeing my ass like this? I can feel you enjoying every movement. It feels good, huh?">>
<<TalkMC "Yeah, keep moving, you're perfect in that position.">>
<<TalkMC "Come on, take it to the next level. Do that thing with your tongue and hands, like you're milking a cow.">>
<<TalkRandom "Stripper" "assets/img/misc/oldtown/redlight/stripclub/stripper/1/avatar.webp" "Oh, you naughty boy! A rimjob with a handjob in milking mode? I love the idea, it'll blow your mind. Are you ready for this?">>
<<TalkMC "Absolutely, go ahead, show me your skills. You're an expert, right?">>
<<TalkRandom "Stripper" "assets/img/misc/oldtown/redlight/stripclub/stripper/1/avatar.webp" "Of course, honey. This outfit is to make you feel like a king. Imagine the pleasure, I'm going to milk you dry.">>
<video src="assets/img/misc/oldtown/redlight/stripclub/stripper/1/6.mp4"/>
<<TalkMC "Damn, you're incredible, keep it up. I feel like I'm going to cum on you, beautiful.">>
<<TalkRandom "Stripper" "assets/img/misc/oldtown/redlight/stripclub/stripper/1/avatar.webp" "Yes, baby, give it to me. I want to feel your juice on my skin, it's my little guilty pleasure. Go ahead, let yourself go.">>
<<TalkMC "Here we go, take that on your pretty face. You're a real pro at making me explode like that.">>
<video src="assets/img/misc/oldtown/redlight/stripclub/stripper/1/7.mp4"/>
<<TalkRandom "Stripper" "assets/img/misc/oldtown/redlight/stripclub/stripper/1/avatar.webp" "Mmm, it's hot and sticky, I love it. Look at me, I'm covered in you now. You liked the ending, huh?">>
<<InformationUiPopUp "You just climaxed">><<if $Stress <= $StressMin>><em>Stress already at minimum</em><<elseif $Stress > $StressMin>><em>-5 stress</em><<set $Stress -= 5>><</if>>
<</InformationUiPopUp>>
<div class="BottomUiBarCustom">
<<BottomButton "Move">><<link "↩️ Return">><<set $Hour++>><<goto "Stripclub">><</link>><</BottomButton>>
</div><<sound "music" "music.club" true>><<passagebg>><img src="assets/img/misc/oldtown/redlight/stripclub/choicestripper.webp"/><</passagebg>><style>
.sc-menu {
max-width: 1060px;
margin: 24px auto 0;
font-family: 'Georgia', 'Times New Roman', serif;
padding: 0 12px;
}
.sc-header {
text-align: center;
margin-bottom: 28px;
}
.sc-header-title {
font-size: calc(11px + var(--font-boost,0px));
letter-spacing: 4px;
text-transform: uppercase;
color: rgba(255,210,160,0.5);
margin-bottom: 4px;
}
.sc-header-line {
display: flex;
align-items: center;
justify-content: center;
gap: 12px;
color: rgba(255,180,120,0.3);
font-size: calc(13px + var(--font-boost,0px));
}
.sc-header-line::before,
.sc-header-line::after {
content: '';
height: 1px;
width: 60px;
background: linear-gradient(90deg, transparent, rgba(255,180,100,0.35), transparent);
}
.sc-row {
display: flex;
gap: clamp(10px,2vw,20px);
justify-content: center;
align-items: stretch;
flex-wrap: wrap;
}
.sc-col {
width: clamp(220px,28vw,310px);
flex: 0 0 clamp(220px,28vw,310px);
display: flex;
flex-direction: column;
}
.sc-click {
display: block;
text-decoration: none;
flex: 1;
}
.sc-card {
width: 100%;
aspect-ratio: 3 / 4;
border-radius: 4px;
border: 1px solid rgba(255,180,100,0.18);
overflow: hidden;
cursor: pointer;
position: relative;
transition: transform 140ms ease, border-color 140ms ease;
display: block;
}
.sc-card::after {
content: '';
position: absolute;
inset: 0;
background: linear-gradient(
180deg,
transparent 40%,
rgba(10,5,0,0.55) 75%,
rgba(10,5,0,0.85) 100%
);
pointer-events: none;
z-index: 1;
}
.sc-card:hover {
transform: translateY(-3px);
border-color: rgba(255,180,100,0.42);
}
.sc-card img {
display: block;
width: 100% !important;
min-width: 0 !important;
height: 100% !important;
object-fit: cover;
object-position: center top;
position: absolute;
inset: 0;
}
.sc-card-footer {
position: absolute;
bottom: 0;
left: 0;
right: 0;
padding: clamp(8px,2vw,14px) clamp(10px,2vw,16px);
z-index: 2;
display: flex;
align-items: flex-end;
justify-content: space-between;
flex-wrap: wrap;
gap: 6px;
}
.sc-name {
font-family: 'Georgia', serif;
font-size: clamp(14px,2vw,19px);
font-style: italic;
color: rgba(255,235,200,0.95);
line-height: 1;
text-shadow: 0 1px 8px rgba(0,0,0,0.8);
}
.sc-price {
font-family: system-ui, sans-serif;
font-size: calc(12px + var(--font-boost,0px));
letter-spacing: 1px;
color: rgba(255,200,120,0.85);
background: rgba(0,0,0,0.5);
border: 1px solid rgba(255,180,100,0.25);
border-radius: 2px;
padding: 4px 9px;
}
.sc-box {
margin-top: 10px;
padding: 11px 14px;
border-top: 1px solid rgba(255,180,100,0.14);
}
.sc-info {
font-size: calc(12px + var(--font-boost,0px));
line-height: 1.6;
color: rgba(255,235,200,0.75);
text-align: justify;
hyphens: auto;
}
.sc-toast {
position: fixed;
bottom: 80px;
left: 50%;
transform: translateX(-50%) translateY(12px);
background: rgba(12,4,2,0.92);
border: 1px solid rgba(180,60,40,0.55);
border-radius: 3px;
padding: 10px 22px;
display: flex;
align-items: center;
gap: 10px;
opacity: 0;
pointer-events: none;
transition: opacity 220ms ease, transform 220ms ease;
z-index: 9999;
white-space: nowrap;
}
.sc-toast.visible {
opacity: 1;
transform: translateX(-50%) translateY(0);
}
.sc-toast-icon {
font-size: 14px;
color: rgba(200,70,50,0.9);
}
.sc-toast-text {
font-family: system-ui, sans-serif;
font-size: calc(12px + var(--font-boost,0px));
letter-spacing: 0.5px;
color: rgba(255,200,180,0.85);
}
.sc-toast-amount {
font-weight: 600;
color: rgba(255,180,100,0.9);
}
@media (max-width: 720px) {
.sc-col {
width: min(310px, 90vw);
flex: 0 0 min(310px, 90vw);
}
}
</style><<if $Money is undefined>><<set $Money = 0>><</if>><div class="sc-menu"><div class="sc-header"><div class="sc-header-title">Private Entertainment</div><div class="sc-header-line">choose your companion</div></div><div class="sc-row">
<div class="sc-col"><<link "<span class='sc-click'><div class='sc-card'><img src='assets/img/misc/oldtown/redlight/stripclub/stripper/1/avatar.webp'><div class='sc-card-footer'><span class='sc-name'>NyLust</span><span class='sc-price'>500$</span></div></div></span>">><<if $Money >= 500>><<set $Money -= 500>><<goto "Stripper1">><<else>><<script>>window.scShowToast("500$");<</script>><</if>><</link>><div class="sc-box"><div class="sc-info">NyLust is a 36-year-old African-American stripper, voluptuous, dark skin, large breasts, round buttocks, full lips and a seductive gaze. Confident and playful, she loves to tease and provoke while being very open.</div></div></div>
<div class="sc-col"><<link "<span class='sc-click'><div class='sc-card'><img src='assets/img/misc/oldtown/redlight/stripclub/stripper/2/avatar.jpg'><div class='sc-card-footer'><span class='sc-name'>Ima Blue</span><span class='sc-price'>750$</span></div></div></span>">><<if $Money >= 750>><<set $Money -= 750>><<goto "Stripper2">><<else>><<script>>window.scShowToast("750$");<</script>><</if>><</link>><div class="sc-box"><div class="sc-info">Ima Blue is a 25-year-old African-American stripper, voluptuous with light skin, short black hair, expressive eyes, full lips and a curvy figure with round buttocks. She is confident, submissive, and loves being dominated.</div></div></div>
<div class="sc-col"><<link "<span class='sc-click'><div class='sc-card'><img src='assets/img/misc/oldtown/redlight/stripclub/stripper/3/doubleavatar.jpg'><div class='sc-card-footer'><span class='sc-name'>Valeela & Angel</span><span class='sc-price'>1000$</span></div></div></span>">><<if $Money >= 1000>><<set $Money -= 1000>><<goto "Stripper3">><<else>><<script>>window.scShowToast("1000$");<</script>><</if>><</link>><div class="sc-box"><div class="sc-info">Valeela (23): gothic look, light skin, long purple hair, slim body, playful and submissive. Angel (43): pale skin, short black hair, slim and curvy, dominant and rebellious, leads with passion.</div></div></div></div></div>
<div class="BottomUiBarCustom">
<<BottomButton "Move">>[[↩️ Return|Stripclub]]<</BottomButton>>
</div><<script>>
window.scShowToast = function(amount) {
var toast = document.getElementById("sc-toast");
var need = document.getElementById("sc-toast-need");
if (!toast || !need) return;
need.textContent = amount;
clearTimeout(window._scToastTimer);
toast.classList.remove("visible");
void toast.offsetWidth;
toast.classList.add("visible");
window._scToastTimer = setTimeout(function() {
toast.classList.remove("visible");
}, 2800);
};<</script>><div id="sc-toast" class="sc-toast"><span class="sc-toast-icon">⚠</span><span class="sc-toast-text">Not enough cash, you need <span id="sc-toast-need" class="sc-toast-amount"></span></span></div><<sound "music" "music.club" true>><<passagebg>><img src="assets/img/misc/oldtown/redlight/stripclub/choicestripper.webp"/><</passagebg>><video src="assets/img/misc/oldtown/redlight/stripclub/stripper/2/1.mp4"/>
<<TalkMC "Wow, you look absolutely stunning standing there in front of me. I can't help but stare at you from head to toe.">>
<<TalkRandom "Stripper" "assets/img/misc/oldtown/redlight/stripclub/stripper/2/avatar.jpg" "Thanks, honey. I love it when guys like you look at me like that. It gives me chills. You like what you see, huh?">>
<<TalkMC "Absolutely. You're perfect, with those curves. Come a little closer, let me admire every detail.">>
<<TalkRandom "Stripper" "assets/img/misc/oldtown/redlight/stripclub/stripper/2/avatar.jpg" "With pleasure. I'm here for you, right close by. Tell me what you want to explore first.">>
<<TalkMC "Open your mouth, beautiful. I want to feel your tongue around my fingers. Are you ready to play a little?">>
<video src="assets/img/misc/oldtown/redlight/stripclub/stripper/2/2.mp4"/>
<<TalkRandom "Stripper" "assets/img/misc/oldtown/redlight/stripclub/stripper/2/avatar.jpg" "Mmm, yes, go ahead. I love it when you take control like that. Your fingers in my mouth, it's exciting.">>
<<TalkMC "It feels good, huh? Let the drool run down your breasts, show me how wet you are for me.">>
<<TalkRandom "Stripper" "assets/img/misc/oldtown/redlight/stripclub/stripper/2/avatar.jpg" "Oh, baby, look at that... It's sliding everywhere. Do you like seeing me like this, all slobbery for you?">>
<<TalkMC "On your knees now. Take me in your mouth, suck me good like you know how.">>
<<TalkRandom "Stripper" "assets/img/misc/oldtown/redlight/stripclub/stripper/2/avatar.jpg" "With pleasure. I'm going to suck you slowly, make you feel every inch. You're hard for me, aren't you?">>
<video src="assets/img/misc/oldtown/redlight/stripclub/stripper/2/3.mp4"/>
<<TalkMC "Fuck, yes, keep going. Your mouth is magic, you're an expert.">>
<<TalkRandom "Stripper" "assets/img/misc/oldtown/redlight/stripclub/stripper/2/avatar.jpg" "Mmm, I love sucking you like this. Tell me if you want it deeper or faster, baby.">>
<<TalkMC "Here, I'm taking your head now. I'm going to make you swallow everything.">>
<<TalkRandom "Stripper" "assets/img/misc/oldtown/redlight/stripclub/stripper/2/avatar.jpg" "Oh, go ahead, control me. I love it when you push like that, it drives me crazy.">>
<video src="assets/img/misc/oldtown/redlight/stripclub/stripper/2/4.mp4"/>
<<TalkMC "That's it, take it all. You're a good girl for deep throating.">>
<<TalkRandom "Stripper" "assets/img/misc/oldtown/redlight/stripclub/stripper/2/avatar.jpg" "I know, baby. I'm gonna suck you until you beg for more.">>
<<TalkMC "Turn around, get on all fours. I'm going to take you doggy style, fuck you hard like you deserve.">>
<video src="assets/img/misc/oldtown/redlight/stripclub/stripper/2/5.mp4"/>
<<TalkRandom "Stripper" "assets/img/misc/oldtown/redlight/stripclub/stripper/2/avatar.jpg" "Yes, baby, take me like that. I love feeling your cock inside me.">>
<<TalkMC "Damn, you're tight. Move with me, show me how much you love it.">>
<<TalkRandom "Stripper" "assets/img/misc/oldtown/redlight/stripclub/stripper/2/avatar.jpg" "Mmm, that's perfect. Fuck me harder, I'm all yours.">>
<<TalkMC "Sit on me, with your back to me, show me your skills.">>
<video src="assets/img/misc/oldtown/redlight/stripclub/stripper/2/6.mp4"/>
<<TalkRandom "Stripper" "assets/img/misc/oldtown/redlight/stripclub/stripper/2/avatar.jpg" "With pleasure. Watch me move like this for you. It feels good, huh?">>
<<TalkMC "Yeah, keep going. You look incredible in that pose, I can feel everything.">>
<<TalkRandom "Stripper" "assets/img/misc/oldtown/redlight/stripclub/stripper/2/avatar.jpg" "Mmm, I love it. Tell me if you want me to go faster.">>
<<TalkMC "Kneel down one last time. I'm going to cum on you, all over your body.">>
<<TalkRandom "Stripper" "assets/img/misc/oldtown/redlight/stripclub/stripper/2/avatar.jpg" "Yes, baby, cover me. I can't wait for your juice.">>
<img src="assets/img/misc/oldtown/redlight/stripclub/stripper/2/7.webp"/>
<<TalkRandom "Stripper" "assets/img/misc/oldtown/redlight/stripclub/stripper/2/avatar.jpg" "Mmm, it's hot everywhere. I love finishing like this, covered in you. You liked that, huh?">>
<<InformationUiPopUp "You just climaxed">><<if $Stress <= $StressMin>><em>Stress already at minimum</em><<elseif $Stress > $StressMin>><em>-5 stress</em><<set $Stress -= 5>><</if>>
<</InformationUiPopUp>>
<div class="BottomUiBarCustom">
<<BottomButton "Move">><<link "↩️ Return">><<set $Hour++>><<goto "Stripclub">><</link>><</BottomButton>>
</div><<sound "music" "music.club" true>><<passagebg>><img src="assets/img/misc/oldtown/redlight/stripclub/choicestripper.webp"/><</passagebg>><video src="assets/img/misc/oldtown/redlight/stripclub/stripper/3/1.mp4"/>
<<TalkMC "Wow, girls, you look amazing on that pole. I could watch you all night long.">>
<<TalkRandom "Stripper" "assets/img/misc/oldtown/redlight/stripclub/stripper/3/avatar1.jpg" "You like watching us rub ourselves like this, huh? It's our little show for you, honey.">>
<<TalkRandom "Stripper" "assets/img/misc/oldtown/redlight/stripclub/stripper/3/avatar2.jpg" "Yeah, we're sliding and spinning to turn you on. Like what you see?">>
<<TalkMC "Show me how hot you are together on that pole.">>
<video src="assets/img/misc/oldtown/redlight/stripclub/stripper/3/2.mp4"/>
<<TalkMC "Damn, you touch each other like that with your breasts? That's even better, keep caressing each other.">>
<<TalkRandom "Stripper" "assets/img/misc/oldtown/redlight/stripclub/stripper/3/avatar1.jpg" "Mmm, do you like it when we touch each other? It turns us on to know you're watching.">>
<<TalkMC "On your knees, girls. Jerk me off like you know how.">>
<video src="assets/img/misc/oldtown/redlight/stripclub/stripper/3/3.mp4"/>
<<TalkRandom "Stripper" "assets/img/misc/oldtown/redlight/stripclub/stripper/3/avatar2.jpg" "With pleasure, honey. I'm going to jerk you off gently, make you even harder. Is that okay?">>
<<TalkRandom "Stripper" "assets/img/misc/oldtown/redlight/stripclub/stripper/3/avatar2.jpg" "Watch her do it, she's an expert. You like her hand on you, huh?">>
<<TalkMC "Yeah, keep going, speed it up a little.">>
<<TalkMC "Valeela, your turn. Take me in your mouth, suck me deep.">>
<<TalkRandom "Stripper" "assets/img/misc/oldtown/redlight/stripclub/stripper/3/avatar1.jpg" "Mmm, yes, I'm going to suck you like a pro. Your cock in my mouth, it's perfect.">>
<video src="assets/img/misc/oldtown/redlight/stripclub/stripper/3/4.mp4"/>
<<TalkRandom "Stripper" "assets/img/misc/oldtown/redlight/stripclub/stripper/3/avatar2.jpg" "She sucks you well, huh? Look at her go, she loves it.">>
<<TalkRandom "Stripper" "assets/img/misc/oldtown/redlight/stripclub/stripper/3/avatar2.jpg" "Do you like it when I crack my outfit like this? Look at my ass, all exposed for you.">>
<video src="assets/img/misc/oldtown/redlight/stripclub/stripper/3/5.mp4"/>
<<TalkRandom "Stripper" "assets/img/misc/oldtown/redlight/stripclub/stripper/3/avatar1.jpg" "She's sexy, huh? Those ripped fishnets turn you on even more.">>
<<TalkMC "Okay, climb on top of me. Fuck me like that, with your back to me.">>
<video src="assets/img/misc/oldtown/redlight/stripclub/stripper/3/6.mp4"/>
<<TalkRandom "Stripper" "assets/img/misc/oldtown/redlight/stripclub/stripper/3/avatar2.jpg" "Yes, baby, can you feel me moving on top of you? Does that feel good?">>
<<TalkRandom "Stripper" "assets/img/misc/oldtown/redlight/stripclub/stripper/3/avatar1.jpg" "Watch her ride, she's made for it. Do you like the view?">>
<<TalkMC "Hell, yes.">>
<<TalkMC "You, suck me some more. And you, hold her head so she goes deeper.">>
<<TalkRandom "Stripper" "assets/img/misc/oldtown/redlight/stripclub/stripper/3/avatar2.jpg" "With pleasure, I'll hold her head. Go ahead, Valeela, suck him good.">>
<video src="assets/img/misc/oldtown/redlight/stripclub/stripper/3/7.mp4"/>
<<TalkMC "Yeah, keep going, girls.">><<TalkMC "Now get on top of me.">>
<video src="assets/img/misc/oldtown/redlight/stripclub/stripper/3/8.mp4"/>
<<TalkRandom "Stripper" "assets/img/misc/oldtown/redlight/stripclub/stripper/3/avatar2.jpg" "I'm going to rub your clit, Valeela. Until you cum, huh, baby?">>
<<TalkMC "That's it, fuck her faster. Make her cum with me.">>
<<TalkMC "Turn around and keep going. And you, sit down and finger yourself for me.">>
<video src="assets/img/misc/oldtown/redlight/stripclub/stripper/3/9.mp4"/>
<<TalkRandom "Stripper" "assets/img/misc/oldtown/redlight/stripclub/stripper/3/avatar1.jpg" "Mmm, Angel, finger yourself, we're going to cum together.">>
<<TalkRandom "Stripper" "assets/img/misc/oldtown/redlight/stripclub/stripper/3/avatar2.jpg" "Oh yes, fuck, watch me cum.">>
<<TalkMC "On your knees, both of you. I'm going to cum on both your faces.">>
<<TalkRandom "Stripper" "assets/img/misc/oldtown/redlight/stripclub/stripper/3/avatar1.jpg" "Yes, cover me first. I'm waiting for your cum on my face.">>
<video src="assets/img/misc/oldtown/redlight/stripclub/stripper/3/11.mp4"/>
<video src="assets/img/misc/oldtown/redlight/stripclub/stripper/3/10.mp4"/>
<<TalkMC "Take it all on your pretty faces.">>
<<InformationUiPopUp "You just climaxed">><<if $Stress <= $StressMin>><em>Stress already at minimum</em><<elseif $Stress > $StressMin>><em>-5 stress</em><<set $Stress -= 5>><</if>>
<</InformationUiPopUp>>
<div class="BottomUiBarCustom">
<<BottomButton "Move">><<link "↩️ Return">><<set $Hour++>><<goto "Stripclub">><</link>><</BottomButton>>
</div><<bgpause>><div id="questui-root"></div><<script>>
(function(){
function esc(s){return String(s==null?"":s).replace(/[&<>"']/g,function(c){return({"&":"&","<":"<",">":">",'"':""","'":"'"}[c]);});}
function boolV(path){
try{
if(!path) return false;
var reserved=["true","false","undefined","null","and","or","not"];
var expr=String(path).trim();
if(expr[0]==="$") expr=expr.slice(1);
expr=expr.replace(/\band\b/g,"&&").replace(/\bor\b/g,"||").replace(/\bnot\b/g,"!");
expr=expr.replace(/\$?([A-Za-z_][A-Za-z0-9_]*)\.([A-Za-z_][A-Za-z0-9_]*)/g,function(match,obj,prop){
if(reserved.indexOf(obj)!==-1)return match;
var o=State.variables[obj];
if(o===undefined||o===null)return "undefined";
var v=o[prop];
if(v===undefined)return "undefined";
if(typeof v==="string")return '"'+v+'"';
return String(v);
});
expr=expr.replace(/\$?([A-Za-z_][A-Za-z0-9_]*)/g,function(match,name){
if(reserved.indexOf(name)!==-1)return name;
var v=State.variables[name];
if(v===undefined)return "undefined";
if(typeof v==="string")return '"'+v+'"';
return String(v);
});
return !!eval(expr);
}catch(e){return false;}
}
function resolveText(str){
return str.replace(/\{\{([A-Za-z_][A-Za-z0-9_]*)\.([A-Za-z_][A-Za-z0-9_]*)\}\}/g,function(match,obj,prop){
var o=State.variables[obj];
if(!o)return match;
return o[prop]!=null?String(o[prop]):match;
});
}
function getScrollTarget(){
var hb=document.getElementById("hubpass-body");
if(hb)return hb;
return document.scrollingElement||document.documentElement;
}
function forceScrollTop(){
try{var st=getScrollTarget();if(st)st.scrollTop=0;window.scrollTo(0,0);}catch(e){}
try{var ql=document.querySelector("#questui-root .qList");if(ql)ql.scrollTop=0;var rp=document.querySelector("#questui-root .qRightPanel");if(rp)rp.scrollTop=0;}catch(e){}
}
function questStats(q){
var steps=q.steps||[];
var total=steps.length||1;
var done=0;
var anyOpen=false;
for(var i=0;i<steps.length;i++){
var st=steps[i];
var fin=boolV(st.finish);
var cur=boolV(st.current);
if(fin)done++;
if(fin||cur)anyOpen=true;
}
var pct=Math.round((done/total)*100);
var isDone=(done===total);
var isLocked=!anyOpen&&!isDone;
return{total:total,done:done,pct:pct,isDone:isDone,isLocked:isLocked};
}
function stepState(st){
var fin=boolV(st.finish);
var cur=boolV(st.current);
if(fin)return "done";
if(cur)return "current";
return "locked";
}
function pickDefault(list,mode){
if(mode==="done"){var done=list.filter(function(q){return questStats(q).isDone;});return done[0]?done[0].id:(list[0]?list[0].id:null);}
var unlocked=list.filter(function(q){var s=questStats(q);return !s.isLocked&&!s.isDone;});
return unlocked[0]?unlocked[0].id:(list[0]?list[0].id:null);
}
/* =====================================================
INSTITUTIONS
===================================================== */
var institutionList = [
{
key: "university",
name: "University",
icon: "🎓",
npcs: ["NPCPrincipal",],
steps: [
{ text: "Increase the corruption of everyone in this institution to level 1.", current: "$Corruption.university >= 0", finish: "$Corruption.university >= 1" },
{ text: "You must join the university as a professor. To do so, follow the Principal's path. And increase the corruption of everyone in this institution to level 2.", current: "$Corruption.university == 1 || $Corruption.university > 2 && $PlayerWorkUniversity == true", finish: "$Corruption.university >= 2 && $PlayerWorkUniversity == true" },
{ text: "Increase the corruption of everyone in this institution to level 3.", current: "$Corruption.university == 2 && $PlayerWorkUniversity == true", finish: "$Corruption.university >= 3" },
{ text: "Increase the corruption of everyone in this institution to level 4.", current: "$Corruption.university == 3", finish: "$Corruption.university >= 4" },
{ text: "Increase the corruption of everyone in this institution to level 5.", current: "$Corruption.university == 4", finish: "$Corruption.university >= 5" },
]
},
];
/* =====================================================
NPCS
===================================================== */
var npcList = [
{
key: "NPCHousemateFemale",
steps: [
{ text: "First thing in the morning, check the bathroom inside the house.", current: "$NPCHousemateFemale.talklvl == 0", finish: "$NPCHousemateFemale.talklvl >= 1" },
{ text: "Around noon, continue your conversation at the university in classroom number 2.", current: "$NPCHousemateFemale.talklvl == 1", finish: "$NPCHousemateFemale.talklvl >= 2" },
{ text: "You need at least 2 bottles of alcohol. During the afternoon, someone has set up a tent at the back of the garden.", current: "$NPCHousemateFemale.talklvl == 2", finish: "$NPCHousemateFemale.talklvl >= 3" },
{ text: "This afternoon, you are expected in the house garden.", current: "$NPCHousemateFemale.talklvl == 3", finish: "$NPCHousemateFemale.talklvl >= 4" },
{ text: "Fortune favors the early riser; a unexpected encounter awaits you in the bathroom.", current: "$NPCHousemateFemale.talklvl == 4", finish: "$NPCHousemateFemale.talklvl >= 5" },
{ text: "Wait for a text message from her at night. And when night falls, go to your {{NPCHousemateFemale.role}}'s bedroom.", current: "$NPCHousemateFemale.talklvl == 5", finish: "$NPCHousemateFemale.talklvl >= 6" },
]
},
{
key: "NPCHousemateMale",
steps: [
{ text: "WIP", current: "$NPCHousemateMale.talklvl == 0", finish: "$NPCHousemateMale.talklvl >= 1" },
{ text: "WIP", current: "$NPCHousemateMale.talklvl == 1", finish: "$NPCHousemateMale.talklvl >= 2" },
{ text: "WIP", current: "$NPCHousemateMale.talklvl == 2", finish: "$NPCHousemateMale.talklvl >= 3" },
{ text: "WIP", current: "$NPCHousemateMale.talklvl == 3", finish: "$NPCHousemateMale.talklvl >= 4" },
{ text: "WIP", current: "$NPCHousemateMale.talklvl == 4", finish: "$NPCHousemateMale.talklvl >= 5" },
{ text: "WIP", current: "$NPCHousemateMale.talklvl == 5", finish: "$NPCHousemateMale.talklvl >= 6" },
]
},
{
key: "NPCLandlady",
steps: [
{ text: "You must meet the character for the first time, then once that is done, go see them the next morning.", current: "$NPCLandlady.talklvl == 0", finish: "$NPCLandlady.talklvl >= 1" },
{ text: "Reach a minimum corruption level of 2 with your {{NPCHousemateFemale.role}}. Then wait 3 days, and go to the living room at noon.", current: "$NPCLandlady.talklvl == 1", finish: "$NPCLandlady.talklvl >= 2" },
{ text: "Reach a minimum corruption level of 3 with your {{NPCHousemateFemale.role}}. Then wait 3 days, and go to the entrance of the house at noon.", current: "$NPCLandlady.talklvl == 2", finish: "$NPCLandlady.talklvl >= 3" },
{ text: "Reach a minimum corruption level of 4 with your {{NPCHousemateFemale.role}}. Then wait 3 days, and go to the living room at noon.", current: "$NPCLandlady.talklvl == 3", finish: "$NPCLandlady.talklvl >= 4" },
{ text: "You must have completely finished Chapter 4 in Story and have precisely placed a camera in the bathroom. Once that is done, go to the living room during the afternoon and watch TV.", current: "$NPCLandlady.talklvl == 4", finish: "$NPCLandlady.talklvl >= 5" },
{ text: "You must go on your PC in your bedroom, search the internet for a way to buy sleeping medications. Wait 3 days for delivery, then no matter what time of day, go to the entrance of the house. Once all that is done, go to the kitchen at night, put the sedative in a glass of water, then afterwards, go to the living room to give it to {{NPCLandlord.role}}. After that, go to your {{NPCLandlady.role}}'s bedroom, the master bedroom.", current: "$NPCLandlady.talklvl == 5", finish: "$NPCLandlady.talklvl >= 6" },
]
},
{
key: "NPCLandlord",
steps: [
{ text: "WIP", current: "$NPCLandlord.talklvl == 0", finish: "$NPCLandlord.talklvl >= 1" },
{ text: "WIP", current: "$NPCLandlord.talklvl == 1", finish: "$NPCLandlord.talklvl >= 2" },
{ text: "WIP", current: "$NPCLandlord.talklvl == 2", finish: "$NPCLandlord.talklvl >= 3" },
{ text: "WIP", current: "$NPCLandlord.talklvl == 3", finish: "$NPCLandlord.talklvl >= 4" },
{ text: "WIP", current: "$NPCLandlord.talklvl == 4", finish: "$NPCLandlord.talklvl >= 5" },
{ text: "WIP", current: "$NPCLandlord.talklvl == 5", finish: "$NPCLandlord.talklvl >= 6" },
]
},
{
key: "NPCOnlineFriend",
steps: [
{ text: "WIP", current: "$NPCOnlineFriend.talklvl == 0", finish: "$NPCOnlineFriend.talklvl >= 1" },
{ text: "WIP", current: "$NPCOnlineFriend.talklvl == 1", finish: "$NPCOnlineFriend.talklvl >= 2" },
{ text: "WIP", current: "$NPCOnlineFriend.talklvl == 2", finish: "$NPCOnlineFriend.talklvl >= 3" },
{ text: "WIP", current: "$NPCOnlineFriend.talklvl == 3", finish: "$NPCOnlineFriend.talklvl >= 4" },
{ text: "WIP", current: "$NPCOnlineFriend.talklvl == 4", finish: "$NPCOnlineFriend.talklvl >= 5" },
{ text: "WIP", current: "$NPCOnlineFriend.talklvl == 5", finish: "$NPCOnlineFriend.talklvl >= 6" },
]
},
{
key: "NPCLeftNeighbor",
steps: [
{ text: "WIP", current: "$NPCLeftNeighbor.talklvl == 0", finish: "$NPCLeftNeighbor.talklvl >= 1" },
{ text: "WIP", current: "$NPCLeftNeighbor.talklvl == 1", finish: "$NPCLeftNeighbor.talklvl >= 2" },
{ text: "WIP", current: "$NPCLeftNeighbor.talklvl == 2", finish: "$NPCLeftNeighbor.talklvl >= 3" },
{ text: "WIP", current: "$NPCLeftNeighbor.talklvl == 3", finish: "$NPCLeftNeighbor.talklvl >= 4" },
{ text: "WIP", current: "$NPCLeftNeighbor.talklvl == 4", finish: "$NPCLeftNeighbor.talklvl >= 5" },
{ text: "WIP", current: "$NPCLeftNeighbor.talklvl == 5", finish: "$NPCLeftNeighbor.talklvl >= 6" },
]
},
{
key: "NPCRightNeighbor",
steps: [
{ text: "WIP", current: "$NPCRightNeighbor.talklvl == 0", finish: "$NPCRightNeighbor.talklvl >= 1" },
{ text: "WIP", current: "$NPCRightNeighbor.talklvl == 1", finish: "$NPCRightNeighbor.talklvl >= 2" },
{ text: "WIP", current: "$NPCRightNeighbor.talklvl == 2", finish: "$NPCRightNeighbor.talklvl >= 3" },
{ text: "WIP", current: "$NPCRightNeighbor.talklvl == 3", finish: "$NPCRightNeighbor.talklvl >= 4" },
{ text: "WIP", current: "$NPCRightNeighbor.talklvl == 4", finish: "$NPCRightNeighbor.talklvl >= 5" },
{ text: "WIP", current: "$NPCRightNeighbor.talklvl == 5", finish: "$NPCRightNeighbor.talklvl >= 6" },
]
},
{
key: "NPCBestFriend",
steps: [
{ text: "First classes early in the morning.", current: "$NPCBestFriend.talklvl == 0", finish: "$NPCBestFriend.talklvl >= 1" },
{ text: "In lecture hall number 2, around noon.", current: "$NPCBestFriend.talklvl == 1", finish: "$NPCBestFriend.talklvl >= 2" },
{ text: "Wait for a text message from her at afternoon. Then head over to her place in the afternoon.", current: "$NPCBestFriend.talklvl == 2", finish: "$NPCBestFriend.talklvl >= 3" },
{ text: "Go to her place in the afternoon.", current: "$NPCBestFriend.talklvl == 3", finish: "$NPCBestFriend.talklvl >= 4" },
{ text: "Talk with {{NPCTeachLang.name}} in the University Staff Room. And go to her place in the afternoon.", current: "$NPCBestFriend.talklvl == 4", finish: "$NPCBestFriend.talklvl >= 5" },
{ text: "Go to her place in the night.", current: "$NPCBestFriend.talklvl == 5", finish: "$NPCBestFriend.talklvl >= 6" },
]
},
{
key: "NPCMate1",
steps: [
{ text: "In the morning in front of the university, she is waiting for something.", current: "$NPCMate1.talklvl == 0", finish: "$NPCMate1.talklvl >= 1" },
{ text: "In the morning, she is waiting for you with your car.", current: "$NPCMate1.talklvl == 1", finish: "$NPCMate1.talklvl >= 2 and $PlayerHasCar == true" },
{ text: "In the morning, she is already waiting by your car.", current: "$NPCMate1.talklvl == 2", finish: "$NPCMate1.talklvl >= 3 and $PlayerHasCar == true" },
{ text: "Around noon, after class, {{NPCMate1.name}} would like to talk to you.", current: "$NPCMate1.talklvl == 3", finish: "$NPCMate1.talklvl >= 4" },
{ text: "Wait for a text message from her at night. Then head over to her place in the night.", current: "$NPCMate1.talklvl == 4", finish: "$NPCMate1.talklvl >= 5" },
{ text: "You need to buy a chain necklace at the SexShop. Then head over to her place in the afternoon.", current: "$NPCMate1.talklvl == 5", finish: "$NPCMate1.talklvl >= 6" },
]
},
{
key: "NPCMate2",
steps: [
{ text: "In the morning, in Lecture Hall 1 at the university.", current: "$NPCMate2.talklvl == 0", finish: "$NPCMate2.talklvl >= 1" },
{ text: "Around noon, in Lecture Hall 2 at the university.", current: "$NPCMate2.talklvl == 1", finish: "$NPCMate2.talklvl >= 2" },
{ text: "In the university gym during the afternoon.", current: "$NPCMate2.talklvl == 2", finish: "$NPCMate2.talklvl >= 3" },
{ text: "Around noon, in Lecture Hall 2 at the university.", current: "$NPCMate2.talklvl == 3", finish: "$NPCMate2.talklvl >= 4" },
{ text: "In the university gym during the afternoon.", current: "$NPCMate2.talklvl == 4", finish: "$NPCMate2.talklvl >= 5" },
{ text: "Wait for a text message from her at afternoon. Then meet her at the university gym.", current: "$NPCMate2.talklvl == 5", finish: "$NPCMate2.talklvl >= 6" },
]
},
{
key: "NPCMate3",
steps: [
{ text: "In the morning in Lecture Hall 1, meet her for the first time.", current: "$NPCMate3.talklvl == 0", finish: "$NPCMate3.talklvl >= 1" },
{ text: "At noon in Lecture Hall 2, she might need help getting somewhere.", current: "$NPCMate3.talklvl == 1", finish: "$NPCMate3.talklvl >= 2 and $PlayerHasCar == true" },
{ text: "A little treat awaits you at noon in Lecture Hall 2.", current: "$NPCMate3.talklvl == 2", finish: "$NPCMate3.talklvl >= 3" },
{ text: "She might need you and your car to drive her home this afternoon.", current: "$NPCMate3.talklvl == 3", finish: "$NPCMate3.talklvl >= 4 and $PlayerHasCar == true" },
{ text: "Why not go further this time? Accompany her to her home this afternoon with your car.", current: "$NPCMate3.talklvl == 4", finish: "$NPCMate3.talklvl >= 5 and $PlayerHasCar == true" },
{ text: "Wait for a text message from her at night. Buy a body harness at the Sexshop. Then head over to her place at night.", current: "$NPCMate3.talklvl == 5", finish: "$NPCMate3.talklvl >= 6" },
]
},
{
key: "NPCTeachSport",
steps: [
{ text: "WIP", current: "$NPCTeachSport.talklvl == 0", finish: "$NPCTeachSport.talklvl >= 1" },
{ text: "WIP", current: "$NPCTeachSport.talklvl == 1", finish: "$NPCTeachSport.talklvl >= 2" },
{ text: "WIP", current: "$NPCTeachSport.talklvl == 2", finish: "$NPCTeachSport.talklvl >= 3" },
{ text: "WIP", current: "$NPCTeachSport.talklvl == 3", finish: "$NPCTeachSport.talklvl >= 4" },
{ text: "WIP", current: "$NPCTeachSport.talklvl == 4", finish: "$NPCTeachSport.talklvl >= 5" },
{ text: "WIP", current: "$NPCTeachSport.talklvl == 5", finish: "$NPCTeachSport.talklvl >= 6" },
]
},
{
key: "NPCTeachTech",
steps: [
{ text: "WIP", current: "$NPCTeachTech.talklvl == 0", finish: "$NPCTeachTech.talklvl >= 1" },
{ text: "WIP", current: "$NPCTeachTech.talklvl == 1", finish: "$NPCTeachTech.talklvl >= 2" },
{ text: "WIP", current: "$NPCTeachTech.talklvl == 2", finish: "$NPCTeachTech.talklvl >= 3" },
{ text: "WIP", current: "$NPCTeachTech.talklvl == 3", finish: "$NPCTeachTech.talklvl >= 4" },
{ text: "WIP", current: "$NPCTeachTech.talklvl == 4", finish: "$NPCTeachTech.talklvl >= 5" },
{ text: "WIP", current: "$NPCTeachTech.talklvl == 5", finish: "$NPCTeachTech.talklvl >= 6" },
]
},
{
key: "NPCTechLang",
steps: [
{ text: "WIP", current: "$NPCTechLang.talklvl == 0", finish: "$NPCTechLang.talklvl >= 1" },
{ text: "WIP", current: "$NPCTechLang.talklvl == 1", finish: "$NPCTechLang.talklvl >= 2" },
{ text: "WIP", current: "$NPCTechLang.talklvl == 2", finish: "$NPCTechLang.talklvl >= 3" },
{ text: "WIP", current: "$NPCTechLang.talklvl == 3", finish: "$NPCTechLang.talklvl >= 4" },
{ text: "WIP", current: "$NPCTechLang.talklvl == 4", finish: "$NPCTechLang.talklvl >= 5" },
{ text: "WIP", current: "$NPCTechLang.talklvl == 5", finish: "$NPCTechLang.talklvl >= 6" },
]
},
{
key: "NPCPrincipal",
steps: [
{ text: "You must meet her first, then wait for a summons email. Then head to her office at the university.", current: "$NPCPrincipal.talklvl == 0", finish: "$NPCPrincipal.talklvl >= 1" },
{ text: "You must read the university's recruitment announcement to become a professor, search online to apply. Wait a few days for a reply from the principal. Then you must be in your office, in the Teachers lounge at the University. And wait for her to come by, either in the morning, at noon, or in the afternoon.", current: "$NPCPrincipal.talklvl == 1", finish: "$NPCPrincipal.talklvl >= 2" },
{ text: "Go to your Personal Office, in the Teachers Lounge at the University, from there, do more than two Punish a Student. And wait a few days to receive a summons from the principal.", current: "$NPCPrincipal.talklvl == 2", finish: "$NPCPrincipal.talklvl >= 3" },
{ text: "You must be in your office, in the Teachers lounge at the University. And wait for her to come by, either in the morning, at noon, or in the afternoon.", current: "$NPCPrincipal.talklvl == 3", finish: "$NPCPrincipal.talklvl >= 4" },
{ text: "Go to your Personal Office, in the Teachers Lounge at the University, from there, do more than one Private Practical Anatomy Class. You must send her a text message, you must be in your office in the Teachers Lounge at the University. And wait for her to come by, either in the morning, at noon, or in the afternoon.", current: "$NPCPrincipal.talklvl == 4", finish: "$NPCPrincipal.talklvl >= 5" },
{ text: "You can see her in her office in the morning, at noon, and in the afternoon. Then you must wait for an invitation SMS from her at night. And head over to her place in the neighborhood.", current: "$PrincipalChapterCurrent5 == true", finish: "$PrincipalChapter6End == true" },
]
},
{
key: "NPCBossGym",
steps: [
{ text: "WIP", current: "$NPCBossGym.talklvl == 0", finish: "$NPCBossGym.talklvl >= 1" },
{ text: "WIP", current: "$NPCBossGym.talklvl == 1", finish: "$NPCBossGym.talklvl >= 2" },
{ text: "WIP", current: "$NPCBossGym.talklvl == 2", finish: "$NPCBossGym.talklvl >= 3" },
{ text: "WIP", current: "$NPCBossGym.talklvl == 3", finish: "$NPCBossGym.talklvl >= 4" },
{ text: "WIP", current: "$NPCBossGym.talklvl == 4", finish: "$NPCBossGym.talklvl >= 5" },
{ text: "WIP", current: "$NPCBossGym.talklvl == 5", finish: "$NPCBossGym.talklvl >= 6" },
]
},
{
key: "NPCBossMarket",
steps: [
{ text: "WIP", current: "$NPCBossMarket.talklvl == 0", finish: "$NPCBossMarket.talklvl >= 1" },
{ text: "WIP", current: "$NPCBossMarket.talklvl == 1", finish: "$NPCBossMarket.talklvl >= 2" },
{ text: "WIP", current: "$NPCBossMarket.talklvl == 2", finish: "$NPCBossMarket.talklvl >= 3" },
{ text: "WIP", current: "$NPCBossMarket.talklvl == 3", finish: "$NPCBossMarket.talklvl >= 4" },
{ text: "WIP", current: "$NPCBossMarket.talklvl == 4", finish: "$NPCBossMarket.talklvl >= 5" },
{ text: "WIP", current: "$NPCBossMarket.talklvl == 5", finish: "$NPCBossMarket.talklvl >= 6" },
]
},
{
key: "NPCMayor",
steps: [
{ text: "You must progress in the main quest, chapter 6.", current: "$NPCMayor.talklvl == 0", finish: "$NPCMayor.talklvl >= 1" },
{ text: "Wait a few days for a text message from her at noon. And go to City Hall, regardless of the time of day.", current: "$NPCMayor.talklvl == 1", finish: "$NPCMayor.talklvl >= 2" },
{ text: "Wait a few days for a text message from her at noon. And go to City Hall, regardless of the time of day.", current: "$NPCMayor.talklvl == 2", finish: "$NPCMayor.talklvl >= 3" },
{ text: "You must progress in the main quest, chapter 6.", current: "$NPCMayor.talklvl == 3", finish: "$NPCMayor.talklvl >= 4" },
{ text: "You must progress in the main quest, chapter 6.", current: "$NPCMayor.talklvl == 4", finish: "$NPCMayor.talklvl >= 5" },
{ text: "Wait a few days for a text message from her at afternoon. And go to City Hall, regardless of the time of day.", current: "$NPCMayor.talklvl == 5", finish: "$NPCMayor.talklvl >= 6" },
]
},
{
key: "NPCHomeless",
steps: [
{ text: "WIP", current: "$NPCHomeless.talklvl == 0", finish: "$NPCHomeless.talklvl >= 1" },
{ text: "WIP", current: "$NPCHomeless.talklvl == 1", finish: "$NPCHomeless.talklvl >= 2" },
{ text: "WIP", current: "$NPCHomeless.talklvl == 2", finish: "$NPCHomeless.talklvl >= 3" },
{ text: "WIP", current: "$NPCHomeless.talklvl == 3", finish: "$NPCHomeless.talklvl >= 4" },
{ text: "WIP", current: "$NPCHomeless.talklvl == 4", finish: "$NPCHomeless.talklvl >= 5" },
{ text: "WIP", current: "$NPCHomeless.talklvl == 5", finish: "$NPCHomeless.talklvl >= 6" },
]
},
{
key: "NPCSexshop",
steps: [
{ text: "WIP", current: "$NPCSexshop.talklvl == 0", finish: "$NPCSexshop.talklvl >= 1" },
{ text: "WIP", current: "$NPCSexshop.talklvl == 1", finish: "$NPCSexshop.talklvl >= 2" },
{ text: "WIP", current: "$NPCSexshop.talklvl == 2", finish: "$NPCSexshop.talklvl >= 3" },
{ text: "WIP", current: "$NPCSexshop.talklvl == 3", finish: "$NPCSexshop.talklvl >= 4" },
{ text: "WIP", current: "$NPCSexshop.talklvl == 4", finish: "$NPCSexshop.talklvl >= 5" },
{ text: "WIP", current: "$NPCSexshop.talklvl == 5", finish: "$NPCSexshop.talklvl >= 6" },
]
},
];
function getInstLevel(inst){
var V=State.variables;
var min=Infinity;
inst.npcs.forEach(function(key){
var npc=V[key];
var lvl=npc?+npc.lvl||0:0;
if(lvl<min)min=lvl;
});
return min===Infinity?0:Math.min(min,5);
}
function renderTabs(mode){
return '<div class="qTabsWrap">'+
'<div class="qTabGroup">'+
'<div class="qTabGroupLabel">QUESTS</div>'+
'<div class="qTabGroupRow">'+
'<div class="qTab'+(mode==="main"?" isActive":"")+'" data-qmode="main">Main</div>'+
'<div class="qTab'+(mode==="side"?" isActive":"")+'" data-qmode="side">Side</div>'+
'<div class="qTab'+(mode==="done"?" isActive":"")+'" data-qmode="done">Done</div>'+
'</div>'+
'</div>'+
'<div class="qTabGroupDivider"></div>'+
'<div class="qTabGroup">'+
'<div class="qTabGroupLabel">PROFILES</div>'+
'<div class="qTabGroupRow">'+
'<div class="qTab'+(mode==="characters"?" isActive":"")+'" data-qmode="characters">Characters</div>'+
'<div class="qTab'+(mode==="institutionals"?" isActive":"")+'" data-qmode="institutionals">Institutionals</div>'+
'</div>'+
'</div>'+
'</div>';
}
function render(root, data, state){
var mode=state.mode||"main";
var allTotal=data.length;
var allDone=data.filter(function(q){return questStats(q).isDone;}).length;
var charTotal=npcList.length;
var charDone=npcList.filter(function(n){
var nSteps=n.steps||[];
if(nSteps.length===0)return false;
return nSteps.every(function(st){return boolV(st.finish);});
}).length;
var headerCount=
'<div class="qCounts">'+
'<div class="qCount"><span class="qCountIcon">📜</span><span class="qCountDone">'+esc(allDone)+'</span><span class="qCountSep">/</span><span class="qCountTotal">'+esc(allTotal)+'</span></div>'+
'<div class="qCount"><span class="qCountIcon">👤</span><span class="qCountDone">'+esc(charDone)+'</span><span class="qCountSep">/</span><span class="qCountTotal">'+esc(charTotal)+'</span></div>'+
'</div>';
var tabsHtml=renderTabs(mode);
if(mode==="institutionals"){
var selKey=state.instSelectedKey||institutionList[0].key;
var selInst=institutionList.find(function(i){return i.key===selKey;})||institutionList[0];
var V=State.variables;
var instCards=institutionList.map(function(inst){
var lvl=getInstLevel(inst);
var pct=Math.round((lvl/5)*100);
var sel=inst.key===selKey;
return '<div class="qCharCard'+(sel?" isSelected":"")+'" data-instkey="'+esc(inst.key)+'">'+
'<div class="qInstIcon">'+esc(inst.icon)+'</div>'+
'<div class="qCharCardInfo">'+
'<div class="qCharCardName">'+esc(inst.name)+'</div>'+
'<div class="qCharCardRole">'+inst.npcs.length+' members</div>'+
'</div>'+
'<div class="qCharCardPct">'+esc(pct)+'<span class="qCharCardPctSym">%</span></div>'+
'</div>';
}).join('');
var rightHtml='';
if(selInst){
var instLvl=getInstLevel(selInst);
var instPct=Math.round((instLvl/5)*100);
var npcCards=selInst.npcs.map(function(key){
var npc=V[key];
if(!npc)return'';
var img=npc.img||'';
var name=npc.name||key;
var role=npc.role||'';
var lvl=+npc.lvl||0;
return '<div class="qInstNpcRow" data-gotochar="'+esc(key)+'">'+
'<div class="qCharCardImgWrap"><img src="'+esc(img)+'" class="qCharCardImg" alt=""></div>'+
'<div class="qCharCardInfo">'+
'<div class="qCharCardName">'+esc(name)+'</div>'+
'<div class="qCharCardRole">'+esc(role)+'</div>'+
'</div>'+
'<div class="qInstNpcLvl">Lvl <span class="qInstNpcLvlVal">'+esc(lvl)+'</span><span class="qCharStatMax"> / 6</span></div>'+
'<div class="qInstNpcArrow">→</div>'+
'</div>';
}).join('');
var stepsHtml=selInst.steps.map(function(st){
var stt=stepState(st);
var cls=stt==='done'?' isDone':(stt==='current'?' isCurrent':' isLocked');
var bullet=stt==='done'?'✓':(stt==='current'?'•':'');
return '<div class="qObj'+cls+'"><div class="qObjLeft"><div class="qObjMark">'+esc(bullet)+'</div><div class="qObjText">'+esc(resolveText(st.text||''))+'</div></div></div>';
}).join('');
rightHtml=
'<div class="qRightTop">'+
'<div class="qRightMeta">'+
'<div class="qChip">INSTITUTION</div>'+
'<div class="qDot">•</div>'+
'<div class="qZone">'+esc(selInst.icon)+' '+esc(selInst.name)+'</div>'+
'</div>'+
'<div class="qRightTitle">'+esc(selInst.name)+'</div>'+
'</div>'+
'<div class="qInstLevelBar">'+
'<div class="qInstLevelLabel">'+
'<span class="qInstLevelTitle">Corruption Level</span>'+
'<span class="qInstLevelVal">'+esc(instLvl)+' / 5</span>'+
'</div>'+
'<div class="qCardBar" style="height:6px;margin-top:8px;"><div class="qCardBarFill" style="width:'+esc(instPct)+'%"></div></div>'+
'</div>'+
'<div class="qSection">'+
'<div class="qSectionTitle"><span class="qSectionBar"></span>MEMBERS</div>'+
'<div class="qInstNpcList">'+npcCards+'</div>'+
'</div>'+
'<div class="qSection">'+
'<div class="qSectionTitle"><span class="qSectionBar"></span>OBJECTIVES</div>'+
'<div class="qObjList">'+stepsHtml+'</div>'+
'</div>';
}
root.innerHTML=
'<div class="qUI">'+
'<div class="qLeft">'+
'<div class="qLeftHead"><div class="qLeftTitle">STORYS</div>'+headerCount+'</div>'+
tabsHtml+
'<div class="qCharGrid">'+instCards+'</div>'+
'</div>'+
'<div class="qRight"><div class="qRightPanel">'+rightHtml+'</div></div>'+
'</div>';
if(window.applyGlobalFontSize) window.applyGlobalFontSize();
if(window.setup && setup.wikiScanNode) setup.wikiScanNode(root);
forceScrollTop();
return;
}
if(mode==="characters"){
if(!state.charSelectedKey){
for(var ci=0;ci<npcList.length;ci++){
var cn=State.variables[npcList[ci].key];
if(cn&&cn.met!==false){state.charSelectedKey=npcList[ci].key;break;}
}
}
var selNpcDef=state.charSelectedKey?npcList.find(function(n){return n.key===state.charSelectedKey;}):null;
var selNpc=selNpcDef?State.variables[selNpcDef.key]:null;
var charCards=npcList.map(function(n){
var o=State.variables[n.key];
if(!o)return'';
var sel=n.key===state.charSelectedKey;
var nSteps=n.steps||[];
var nDone=0;
for(var si=0;si<nSteps.length;si++){if(boolV(nSteps[si].finish))nDone++;}
var nPct=nSteps.length>0?Math.round((nDone/nSteps.length)*100):0;
return '<div class="qCharCard'+(sel?' isSelected':'')+'" data-charkey="'+esc(n.key)+'">'+
'<div class="qCharCardImgWrap"><img src="'+esc(o.img||'')+'" class="qCharCardImg" alt=""></div>'+
'<div class="qCharCardInfo">'+
'<div class="qCharCardName">'+esc(o.name||'')+'</div>'+
'<div class="qCharCardRole">'+esc(o.role||'')+'</div>'+
'</div>'+
'<div class="qCharCardPct">'+esc(nPct)+'<span class="qCharCardPctSym">%</span></div>'+
'</div>';
}).join('');
var charRightHtml='';
if(selNpc&&selNpcDef){
var charSteps=selNpcDef.steps||[];
var stepsHtml=charSteps.map(function(st){
var stt=stepState(st);
var cls=stt==='done'?' isDone':(stt==='current'?' isCurrent':' isLocked');
var bullet=stt==='done'?'✓':(stt==='current'?'•':'');
return '<div class="qObj'+cls+'"><div class="qObjLeft"><div class="qObjMark">'+esc(bullet)+'</div><div class="qObjText">'+esc(resolveText(st.text||''))+'</div></div></div>';
}).join('');
charRightHtml=
'<div class="qCharDetail">'+
'<div class="qCharDetailHeader">'+
'<img src="'+esc(selNpc.img||'')+'" class="qCharDetailImg" alt="">'+
'<div class="qCharDetailHeaderInfo">'+
'<div class="qCharDetailName">'+esc(selNpc.name||'')+'</div>'+
'<div class="qCharDetailRole">'+esc(selNpc.role||'')+'</div>'+
'</div>'+
'</div>'+
'<div class="qCharDetailStats">'+
'<div class="qCharStat"><div class="qCharStatLabel">LEVEL</div><div class="qCharStatVal">'+esc(selNpc.lvl||0)+'<span class="qCharStatMax"> / 6</span></div></div>'+
'</div>'+
(charSteps.length?'<div class="qSection"><div class="qSectionTitle"><span class="qSectionBar"></span>CHARACTER STORY</div><div class="qObjList">'+stepsHtml+'</div></div>':'')+
'</div>';
}
root.innerHTML=
'<div class="qUI">'+
'<div class="qLeft">'+
'<div class="qLeftHead"><div class="qLeftTitle">STORYS</div>'+headerCount+'</div>'+
tabsHtml+
'<div class="qCharGrid">'+charCards+'</div>'+
'</div>'+
'<div class="qRight"><div class="qRightPanel">'+charRightHtml+'</div></div>'+
'</div>';
if(window.applyGlobalFontSize) window.applyGlobalFontSize();
if(window.setup && setup.wikiScanNode) setup.wikiScanNode(root);
forceScrollTop();
return;
}
var list=data.filter(function(q){
var t=(q.type||"main");
if(mode==="done")return questStats(q).isDone;
if(mode==="side")return t==="side"&&!questStats(q).isDone;
return t==="main"&&!questStats(q).isDone;
});
var selectedId=state.selectedId;
if(!selectedId||!list.some(function(q){return q.id===selectedId;})){
selectedId=pickDefault(list.length?list:data,mode);
state.selectedId=selectedId;
}
var selected=data.find(function(q){return q.id===selectedId;})||(data[0]||null);
var leftCards=list.map(function(q){
var s=questStats(q);
var tag=(q.type||"main")==="side"?"SIDE":"MAIN";
var lockedClass=s.isLocked?" isLocked":"";
var activeClass=(q.id===selectedId)?" isSelected":"";
var progLabel=s.pct+"%";
return '<div class="qCard'+lockedClass+activeClass+'" data-qid="'+esc(q.id)+'">'+
'<div class="qCardTop">'+
'<div class="qCardTitle">'+esc(q.title)+'</div>'+
'<div class="qCardTag">'+esc(tag)+'</div>'+
'</div>'+
'<div class="qCardDesc">'+esc(q.summary||"")+'</div>'+
'<div class="qCardProg">'+
'<div class="qCardProgLabel">Progress</div>'+
'<div class="qCardProgRight">'+
'<div class="qCardBar"><div class="qCardBarFill" style="width:'+esc(progLabel)+'"></div></div>'+
'<div class="qCardPct">'+esc(progLabel)+'</div>'+
'</div>'+
'</div>'+
'</div>';
}).join("");
var rightHeader=selected?
'<div class="qRightTop">'+
'<div class="qRightMeta">'+
'<div class="qChip">CHAPTER '+esc(selected.chapter||"")+'</div>'+
'<div class="qDot">•</div>'+
'<div class="qZone">'+esc((selected.zone&&String(selected.zone).trim())?selected.zone:"None")+'</div>'+
'</div>'+
'<div class="qRightTitle">'+esc(selected.title)+'</div>'+
'</div>':
"";
var briefing=selected?
'<div class="qSection">'+
'<div class="qSectionTitle"><span class="qSectionBar"></span>BRIEFING</div>'+
'<div class="qSectionText">'+esc(selected.briefing||"")+'</div>'+
(selected.quote?'<div class="qQuote">"'+esc(selected.quote)+'"</div>':'')+
'</div>':"";
var objectives="";
if(selected){
var steps=(selected.steps||[]);
objectives=
'<div class="qSection">'+
'<div class="qSectionTitle"><span class="qSectionBar"></span>OBJECTIVES</div>'+
'<div class="qObjList">'+
steps.map(function(st){
var stt=stepState(st);
var cls=stt==="done"?" isDone":(stt==="current"?" isCurrent":" isLocked");
var bullet=stt==="done"?'✓':(stt==="current"?'•':'');
return '<div class="qObj'+cls+'">'+
'<div class="qObjLeft">'+
'<div class="qObjMark">'+esc(bullet)+'</div>'+
'<div class="qObjText">'+esc(resolveText(st.text||''))+'</div>'+
'</div>'+
'</div>';
}).join("")+
'</div>'+
'</div>';
}
root.innerHTML=
'<div class="qUI">'+
'<div class="qLeft">'+
'<div class="qLeftHead"><div class="qLeftTitle">STORYS</div>'+headerCount+'</div>'+
tabsHtml+
'<div class="qList">'+leftCards+'</div>'+
'</div>'+
'<div class="qRight">'+
'<div class="qRightPanel">'+rightHeader+briefing+objectives+'</div>'+
'</div>'+
'</div>';
if(window.applyGlobalFontSize) window.applyGlobalFontSize();
if(window.setup && setup.wikiScanNode) setup.wikiScanNode(root);
forceScrollTop();
}
function bind(root, data, state){
$(root).off("click.questui").on("click.questui",function(ev){
var t=ev.target;
var modeEl=t&&t.closest?t.closest("[data-qmode]"):null;
if(modeEl){state.mode=modeEl.getAttribute("data-qmode")||"main";render(root,data,state);return;}
var gotoChar=t&&t.closest?t.closest("[data-gotochar]"):null;
if(gotoChar){
state.mode="characters";
state.charSelectedKey=gotoChar.getAttribute("data-gotochar");
render(root,data,state);
return;
}
var instCard=t&&t.closest?t.closest("[data-instkey]"):null;
if(instCard){
state.instSelectedKey=instCard.getAttribute("data-instkey");
var qGrid=root.querySelector(".qCharGrid");
var savedScroll=qGrid?qGrid.scrollTop:0;
render(root,data,state);
var qGridAfter=root.querySelector(".qCharGrid");
if(qGridAfter)qGridAfter.scrollTop=savedScroll;
return;
}
var card=t&&t.closest?t.closest("[data-qid]"):null;
if(card){
if(card.classList.contains("isLocked"))return;
state.selectedId=card.getAttribute("data-qid");
var qList=root.querySelector(".qList");
var savedScroll=qList?qList.scrollTop:0;
render(root,data,state);
var qListAfter=root.querySelector(".qList");
if(qListAfter)qListAfter.scrollTop=savedScroll;
return;
}
var charCard=t&&t.closest?t.closest("[data-charkey]"):null;
if(charCard){
if(charCard.classList.contains("isLocked"))return;
state.charSelectedKey=charCard.getAttribute("data-charkey");
var qGrid=root.querySelector(".qCharGrid");
var savedScroll=qGrid?qGrid.scrollTop:0;
render(root,data,state);
var qGridAfter=root.querySelector(".qCharGrid");
if(qGridAfter)qGridAfter.scrollTop=savedScroll;
return;
}
});
$(document).off(":.questuiScrollTop").on(":passagerender",function(){forceScrollTop();});
}
function applyHubBodyNoScroll(root){
var hb=document.getElementById("hubpass-body");
if(!hb)return null;
forceScrollTop();
hb.classList.add("hubpass-body-noscroll");
var mo=new MutationObserver(function(){
var stillThere=document.getElementById("questui-root");
if(!stillThere){
try{hb.classList.remove("hubpass-body-noscroll");}catch(e){}
try{mo.disconnect();}catch(e){}
try{hb.scrollTop=0;}catch(e){}
try{window.scrollTo(0,0);}catch(e){}
}
});
try{mo.observe(hb,{childList:true,subtree:true});}catch(e){}
return mo;
}
function initWhenReady(tries){
var root=document.getElementById("questui-root");
if(!root){if(tries>0)requestAnimationFrame(function(){initWhenReady(tries-1);});return;}
if(root.dataset.qInit==="1")return;
root.dataset.qInit="1";
forceScrollTop();
applyHubBodyNoScroll(root);
/* =====================================================
MAIN QUEST
===================================================== */
var data = [
{
id: "q_ch1",
type: "main",
chapter: 1,
title: "Game Start and Power Initiation",
zone: "Bedroom",
summary: "Begin your journey by discovering your corruption powers.",
briefing: "A mysterious message awakens a strange power within you. Now you can begin building the foundation of your influence.",
quote: "A new world opens up before you.",
steps: [
{ text: "Once in your bedroom, check your computer to read a mysterious email that introduces you to meditation.", current: "$Story1_1Current", finish: "$Story1_1Finish" },
]
},
{
id: "q_ch2",
type: "main",
chapter: 2,
title: "First Job Quest",
zone: "Arena",
summary: "Find a job and secure your first stable income.",
briefing: "You need money and routine. Search the right places, follow the lead, and show up for your interview downtown.",
quote: "A clean front makes dirty work easier.",
steps: [
{ text: "Browse job offers on the Internet.", current: "$Story2_1Current", finish: "$Story2_1Finish" },
{ text: "Sleep to pass the night, then reply to the received email.", current: "$Story2_2Current", finish: "$Story2_2Finish" },
{ text: "Go downtown to the 'Arena' for the job interview and get your first job, earning money.", current: "$Story2_3Current", finish: "$Story2_3Finish" },
]
},
{
id: "q_ch3",
type: "main",
chapter: 3,
title: "Earning Your Place",
zone: "OldTown",
summary: "Raise your reputation and gain access to the underground scene.",
briefing: "As your name spreads, new doors open. Build your image and push deeper into OldTown to meet the people who matter.",
quote: "Respect is a currency, spend it wisely.",
steps: [
{ text: "Raise your Reputation above 50 points by buying better clothes and vehicles.", current: "$Story3_1Current", finish: "$Story3_1Finish" },
{ text: "Otherwise, go to 'OldTown' and visit the 'TrapHouse' to access underground fights and increase your reputation.", current: "$Story3_2Current", finish: "$Story3_2Finish" },
{ text: "Once you reach 75 or more, go to the 'Pit' in OldTown.", current: "$Story3_3Current", finish: "$Story3_3Finish" },
{ text: "Go to the 'TrapHouse' in OldTown to establish your first real contacts with the criminal world.", current: "$Story3_4Current", finish: "$Story3_4Finish" },
]
},
{
id: "q_ch4",
type: "main",
chapter: 4,
title: "Birth of a Porn Empire",
zone: "Home",
summary: "Set up a hidden camera network, collect footage of your home, and start building your underground video business.",
briefing: "You've found a way to make real money, hidden cameras, raw footage, and a black market that pays well. Time to build your empire from the ground up.",
quote: "Privacy is an illusion. Profit is not.",
steps: [
{ text: "Go to the mall and buy one or more hidden cameras.", current: "$Story4_1Current", finish: "$Story4_1Finish" },
{ text: "Install a camera in different rooms in your home.", current: "$Story4_2Current", finish: "$Story4_2Finish" },
{ text: "Find and buy the software on the internet on your PC, which connects the cameras to your computer.", current: "$Story4_3Current", finish: "$Story4_3Finish" },
{ text: "Wait a few days, then open the software, recover the footage and create your first video montage.", current: "$Story4_4Current", finish: "$Story4_4Finish" },
{ text: "Upgrade your PC components to boost performance when creating montages. You can buy components at the Mall, in the Electronic Shop.", current: "$Story4_5Current", finish: "$Story4_5Finish" },
]
},
{
id: "q_ch5",
type: "main",
chapter: 5,
title: "Currently not available, but chapter 6 is.",
zone: "WIP",
summary: "WIP",
briefing: "WIP",
quote: "WIP",
steps: [
{ text: "WIP", current: "$Story5_1Current", finish: "$Story5_1Finish" },
{ text: "WIP", current: "$Story5_2Current", finish: "$Story5_2Finish" },
]
},
/*{
id: "q_ch5",
type: "main",
chapter: 5,
title: "Mall Economic Control",
zone: "Mall",
summary: "Corrupt mall owners and buy shops to generate passive income.",
briefing: "Money is leverage. Control the owners first, then take their businesses piece by piece until the mall becomes yours.",
quote: "Own the market and the city follows.",
steps: [
{ text: "Corrupt the different Mall owners to level 5.", current: "$Story5_1Current", finish: "$Story5_1Finish" },
{ text: "Then buy their shops one by one to generate passive income.", current: "$Story5_2Current", finish: "$Story5_2Finish" },
]
},*/
{
id: "q_ch6",
type: "main",
chapter: 6,
title: "Taking the High Ground",
zone: "City Hall",
summary: "Seize control of Hargrove's future building and make it yours through the mayor.",
briefing: "A stolen file, a corrupted mayor, and thirty million dollars. Do whatever it takes to claim the Financial Quarter building before anyone else does.",
quote: "The right information in the right hands is worth more than any amount of money.",
steps: [
{ text: "You must have a minimum of 25 Fitness, then go to City Hall in the morning and listen to a strange conversation.", current: "$Story6_1Current", finish: "$Story6_1Finish" },
{ text: "Go to the TrapHouse and get equipment to break into City Hall at night.", current: "$Story6_2Current", finish: "$Story6_2Finish" },
{ text: "Break into City Hall at night, retrieve the document, then go back to your room to read it.", current: "$Story6_3Current", finish: "$Story6_3Finish" },
{ text: "Corrupt the mayor up to level 3 using the stolen documents. For this, check the mayor's story progress.", current: "$Story6_4Current", finish: "$Story6_4Finish" },
{ text: "Wait at least 5 days, then walk around the city during noon or the afternoon.", current: "$Story6_5Current", finish: "$Story6_5Finish" },
{ text: "Wait at least 5 days, then walk around the city during the morning, noon or afternoon.", current: "$Story6_6Current", finish: "$Story6_6Finish" },
{ text: "Wait one day, then go to the TrapHouse to ask for help.", current: "$Story6_7Current", finish: "$Story6_7Finish" },
{ text: "Corrupt the mayor up to at least level 4 to get Hargrove's construction cancelled.", current: "$Story6_8Current", finish: "$Story6_8Finish" },
{ text: "Wait at least 5 days for the mayor to send you a text, then go to her office.", current: "$Story6_9Current", finish: "$Story6_9Finish" },
{ text: "Take out a loan at the bank, then wait at least 2 days for a reply by email.", current: "$Story6_10Current", finish: "$Story6_10Finish" },
{ text: "Corrupt the mayor up to level 5 to secure the construction rights for the building in the Financial Quarter.", current: "$Story6_11Current", finish: "$Story6_11Finish" },
{ text: "Wait at least one day, then go to the Financial Quarter at the construction site to launch construction.", current: "$Story6_12Current", finish: "$Story6_12Finish" },
]
},
{
id: "q_ch7",
type: "main",
chapter: 7,
title: "WIP",
zone: "WIP",
summary: "WIP",
briefing: "WIP",
quote: "WIP",
steps: [
{ text: "WIP", current: "$Story7_1Current", finish: "$Story7_1Finish" },
{ text: "WIP", current: "$Story7_2Current", finish: "$Story7_2Finish" },
{ text: "WIP", current: "$Story7_3Current", finish: "$Story7_3Finish" },
]
},
/*{
id: "q_ch7",
type: "main",
chapter: 7,
title: "Educational Control",
zone: "College",
summary: "Take over education to secure a pipeline of talent.",
briefing: "Control the institution, control the future. Push the right law, buy the College, and turn it into your recruitment machine.",
quote: "The cleanest indoctrination wears a diploma.",
steps: [
{ text: "Raise the city corruption to level 3 to pass a law making the university public.", current: "$Story7_1Current", finish: "$Story7_1Finish" },
{ text: "Then raise the Principal to level 5 and go to the 'College' to buy the institution.", current: "$Story7_2Current", finish: "$Story7_2Finish" },
{ text: "This lets you recruit your future researchers directly at the source.", current: "$Story7_3Current", finish: "$Story7_3Finish" },
]
},*/
{
id: "q_ch8",
type: "main",
chapter: 8,
title: "Reproduction Unlock",
zone: "None",
summary: "Complete research to unlock pregnancy mechanics at corruption level 5.",
briefing: "When research concludes, the rules change. Prepare your subjects and run the first tests through your company.",
quote: "Some projects cannot be undone once proven possible.",
steps: [
{ text: "Once research is completed (about 10 days), all women at corruption level 5 can become pregnant during intimate interactions.", current: "$Story8_1Current", finish: "$Story8_1Finish" },
{ text: "Send them to your company to test your new research on them.", current: "$Story8_2Current", finish: "$Story8_2Finish" },
]
},
{
id: "q_ch9",
type: "main",
chapter: 9,
title: "Gang Creation and HQ",
zone: "OldTown",
summary: "Create your gang and claim a permanent HQ in OldTown.",
briefing: "Recruit from the streets, enhance your people, then seize the TrapHouse and make it your central base of operations.",
quote: "A city obeys whoever owns the streets at night.",
steps: [
{ text: "Corrupt the Homeless woman to level 5, then create your street gang by recruiting homeless people.", current: "$Story9_1Current", finish: "$Story9_1Finish" },
{ text: "Start new R&D on human enhancement.", current: "$Story9_2Current", finish: "$Story9_2Finish" },
{ text: "Once completed, transform the homeless into 'superhuman' forms.", current: "$Story9_3Current", finish: "$Story9_3Finish" },
{ text: "Take control of the 'TrapHouse' in 'OldTown' and turn it into your HQ, generating passive income.", current: "$Story9_4Current", finish: "$Story9_4Finish" },
]
},
{
id: "q_ch10",
type: "main",
chapter: 10,
title: "First Police Neutralization",
zone: "None",
summary: "Neutralize law enforcement pressure by corrupting the Police Chief.",
briefing: "Your expansion draws attention. Handle the Police Chief, then secure cover that reduces overall surveillance on your activities.",
quote: "The law is only dangerous when it points at you.",
steps: [
{ text: "Your growing actions inevitably attract law enforcement attention. Corrupt the Police Chief to level 5.", current: "$Story10_1Current", finish: "$Story10_1Finish" },
{ text: "Once done, explicitly ask her to cover your operations as much as possible.", current: "$Story10_2Current", finish: "$Story10_2Finish" },
]
},
{
id: "q_ch11",
type: "main",
chapter: 11,
title: "Prostitution Monopoly",
zone: "None",
summary: "Take control of the prostitution sector and increase passive income.",
briefing: "Corrupt the right owner, then absorb or crush the competition until a single network remains, loyal and profitable.",
quote: "Monopolies are peace agreements written in money.",
steps: [
{ text: "Corrupt the Sex Shop owner to level 5.", current: "$Story11_1Current", finish: "$Story11_1Finish" },
{ text: "Then take control of the prostitution sector by buying out or dominating existing networks.", current: "$Story11_2Current", finish: "$Story11_2Finish" },
{ text: "You can use level 5 characters as prostitutes, generating even more passive income.", current: "$Story11_3Current", finish: "$Story11_3Finish" },
]
},
{
id: "q_ch12",
type: "main",
chapter: 12,
title: "Accelerated Child Growth",
zone: "None",
summary: "Use research to rapidly grow children into loyal adults and strengthen your control.",
briefing: "Speed turns a plan into an empire. Apply artificial growth, then deploy the results for income and reduced surveillance.",
quote: "Time is the most expensive resource. Buy it back.",
steps: [
{ text: "Each impregnated woman will give birth. Through your research company, apply artificial growth (7 days) to turn them into loyal adults.", current: "$Story12_1Current", finish: "$Story12_1Finish" },
{ text: "Use them as gang soldiers or prostitutes for income.", current: "$Story12_2Current", finish: "$Story12_2Finish" },
]
},
{
id: "q_ch13",
type: "main",
chapter: 13,
title: "Territorial Domination",
zone: "None",
summary: "Take control of every district through gang warfare and expansion.",
briefing: "District by district, remove rivals and lock the city under your rule to generate stable, citywide passive income.",
quote: "Borders are just places you haven't enforced yet.",
steps: [
{ text: "Use your gang to take control of all city districts through fights against other gangs, generating passive income.", current: "$Story13_1Current", finish: "$Story13_1Finish" },
]
},
{
id: "q_ch14",
type: "main",
chapter: 14,
title: "Political Ascension",
zone: "None",
summary: "Reach the top of the city's political hierarchy and secure full control.",
briefing: "Finish corrupting the Mayor, raise the city to maximum corruption, and seize the position that makes your power official.",
quote: "A crown is just a contract everyone agrees to obey.",
steps: [
{ text: "Corrupt the Mayor to level 5.", current: "$Story14_1Current", finish: "$Story14_1Finish" },
{ text: "Raise the city corruption to level 5.", current: "$Story14_2Current", finish: "$Story14_2Finish" },
{ text: "Become Co-Mayor through a rigged vote, unlocking full control over the city administration.", current: "$Story14_3Current", finish: "$Story14_3Finish" },
]
},
{
id: "q_ch15",
type: "main",
chapter: 15,
title: "Final Police Neutralization",
zone: "None",
summary: "Remove the last arrest risk by turning the police into allies.",
briefing: "Raise the Police Captain to full corruption and pass the law that ends all consequences.",
quote: "The safest prison is the one you command.",
steps: [
{ text: "Raise the Police Captain's corruption to level 5.", current: "$Story15_1Current", finish: "$Story15_1Finish" },
{ text: "Now as Co-Mayor, pass a law making the police your ally, eliminating all risk of arrest.", current: "$Story15_2Current", finish: "$Story15_2Finish" },
]
},
{
id: "q_ch16",
type: "main",
chapter: 16,
title: "Final Laws and Victory",
zone: "None",
summary: "Pass the final law and complete your total domination of the city.",
briefing: "With the city under your control, you can legalize what was forbidden and end the story as the absolute master.",
quote: "When everything is permitted, only your will remains.",
steps: [
{ text: "As Co-Mayor, pass the ultimate corruption level 6 law, legalizing prostitution and drugs.", current: "$Story16_1Current", finish: "$Story16_1Finish" },
{ text: "The city is fully corrupted: end of the game, you are the absolute master.", current: "$Story16_2Current", finish: "$Story16_2Finish" },
]
},
];
var state=State.variables._QuestUIState||{mode:"main",selectedId:null,charSelectedKey:null,instSelectedKey:null};
State.variables._QuestUIState=state;
if(window._questOpenInst){
state.mode="institutionals";
state.instSelectedKey=window._questOpenInst;
window._questOpenInst=null;
}
root._questRender=function(){ render(root,data,state); };
render(root,data,state);
bind(root,data,state);
}
initWhenReady(120);
})();
<</script>><style>
#questui-root{width:100%;height:100%;}
#hubpass-body.hubpass-body-noscroll{overflow:hidden !important;padding:0 !important;}
.qUI{display:grid;grid-template-columns:clamp(280px,35%,520px) 1fr;gap:24px;padding:clamp(14px,2vw,22px) clamp(16px,2vw,26px);height:100%;overflow:hidden;box-sizing:border-box;}
.qLeft{display:flex;flex-direction:column;gap:14px;min-height:0;}
.qLeftHead{display:flex;align-items:flex-end;justify-content:space-between;padding:6px 4px 0 4px;flex:0 0 auto;flex-wrap:wrap;gap:8px;}
.qLeftTitle{font-size:calc(18px + var(--font-boost,0px));font-weight:900;letter-spacing:.02em;color:rgba(255,255,255,.96);}
.qCounts{display:flex;gap:14px;align-items:flex-end;}
.qCount{display:flex;align-items:center;gap:4px;font-weight:800;letter-spacing:.02em;}
.qCountIcon{font-size:calc(16px + var(--font-boost,0px));opacity:.85;}
.qCountDone{color:#e65763;font-size:calc(16px + var(--font-boost,0px));}
.qCountSep{color:rgba(255,255,255,.55);font-size:calc(14px + var(--font-boost,0px));align-self:flex-end;}
.qCountTotal{color:rgba(255,255,255,.75);font-size:calc(14px + var(--font-boost,0px));align-self:flex-end;}
.qTabsWrap{display:flex;align-items:flex-end;gap:16px;padding:0 4px;flex:0 0 auto;flex-wrap:wrap;}
.qTabGroup{display:flex;flex-direction:column;gap:6px;}
.qTabGroupLabel{font-size:calc(14px + var(--font-boost,0px));font-weight:900;letter-spacing:.16em;text-transform:uppercase;color:rgba(255,255,255,.65);padding-left:2px;}
.qTabGroupRow{display:flex;gap:6px;flex-wrap:wrap;}
.qTabGroupDivider{width:1px;background:rgba(255,255,255,.15);align-self:stretch;margin-bottom:2px;}
.qTab{padding:6px 14px;border-radius:5px;background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.10);color:rgba(255,255,255,.85);font-weight:800;letter-spacing:.12em;font-size:calc(14px + var(--font-boost,0px));cursor:pointer;user-select:none;}
.qTab.isActive{background:rgba(230,87,99,.15);border-color:rgba(230,87,99,.45);color:rgba(230,87,99,.98);}
.qList{display:flex;flex-direction:column;gap:14px;padding:0 4px 10px 4px;overflow:auto;min-height:0;flex:1 1 auto;}
.qCard{background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.10);border-radius:0 10px 10px 0;padding:clamp(10px,2vw,14px) clamp(12px,2vw,16px);box-shadow:0 10px 30px rgba(0,0,0,.35);cursor:pointer;user-select:none;position:relative;flex:0 0 auto;}
.qCard.isSelected{border-left:3px solid rgba(230,87,99,1);}
.qCard.isLocked{filter:blur(3.5px);opacity:.55;pointer-events:none;}
.qCardTop{display:flex;align-items:center;justify-content:space-between;gap:12px;margin-bottom:8px;flex-wrap:wrap;}
.qCardTitle{font-size:calc(16px + var(--font-boost,0px));font-weight:900;color:rgba(255,255,255,.96);}
.qCardTag{font-size:calc(14px + var(--font-boost,0px));font-weight:900;letter-spacing:.12em;padding:3px 8px;border-radius:5px;border:1px solid rgba(255,255,255,.15);color:rgba(255,255,255,.98);background:rgba(230,87,99,.75);}
.qCardDesc{color:rgba(255,255,255,.78);font-size:calc(14px + var(--font-boost,0px));line-height:1.35;margin-bottom:12px;min-height:34px;}
.qCardProg{display:flex;align-items:center;justify-content:space-between;gap:12px;}
.qCardProgLabel{color:rgba(255,255,255,.85);font-size:calc(14px + var(--font-boost,0px));font-weight:800;}
.qCardProgRight{display:flex;align-items:center;gap:10px;width:62%;}
.qCardBar{height:6px;background:rgba(255,255,255,.04);border:1px solid rgba(255,255,255,.10);border-radius:999px;overflow:hidden;flex:1 1 auto;}
.qCardBarFill{height:100%;background:#e65763;border-radius:999px;}
.qCardPct{width:48px;text-align:right;color:rgba(255,255,255,.92);font-size:calc(14px + var(--font-boost,0px));font-weight:900;}
.qRight{display:flex;align-items:stretch;min-height:0;}
.qRightPanel{width:100%;border-radius:14px;padding:clamp(12px,2vw,18px) clamp(14px,2vw,22px);background:rgba(255,255,255,.05);border:1px solid rgba(255,255,255,.12);position:relative;overflow-y:auto;overflow-x:hidden;min-height:0;flex:1 1 auto;}
.qRightTop{position:relative;padding-bottom:16px;border-bottom:1px solid rgba(255,255,255,.10);margin-bottom:16px;}
.qRightMeta{display:flex;align-items:center;gap:8px;color:rgba(255,255,255,.85);font-weight:800;letter-spacing:.10em;font-size:calc(14px + var(--font-boost,0px));text-transform:uppercase;flex-wrap:wrap;}
.qChip{padding:2px 8px;border-radius:6px;border:1px solid rgba(230,87,99,.45);background:rgba(230,87,99,.15);color:rgba(230,87,99,.98);font-weight:900;}
.qDot{opacity:.55;}
.qZone{opacity:.92;}
.qRightTitle{margin-top:10px;font-size:calc(18px + var(--font-boost,0px));font-weight:950;letter-spacing:.01em;color:rgba(255,255,255,.98);line-height:1.05;}
.qSection{position:relative;margin-top:18px;}
.qSectionTitle{display:flex;align-items:center;gap:10px;font-size:calc(14px + var(--font-boost,0px));font-weight:950;letter-spacing:.12em;text-transform:uppercase;color:rgba(255,255,255,.92);margin-bottom:8px;}
.qSectionBar{width:2px;height:14px;background:#e65763;border-radius:999px;}
.qSectionText{color:rgba(255,255,255,.85);line-height:1.45;font-size:calc(14px + var(--font-boost,0px));max-width:840px;}
.qQuote{margin-top:12px;color:rgba(255,255,255,.92);font-style:italic;font-size:calc(14px + var(--font-boost,0px));max-width:840px;}
.qObjList{display:flex;flex-direction:column;gap:10px;margin-top:8px;}
.qObj{border-radius:10px;padding:clamp(8px,2vw,12px) clamp(10px,2vw,14px);border:1px solid rgba(255,255,255,.12);background:rgba(255,255,255,.03);}
.qObjLeft{display:flex;align-items:flex-start;gap:10px;}
.qObjMark{width:18px;height:18px;border-radius:999px;display:inline-flex;align-items:center;justify-content:center;font-weight:900;font-size:calc(14px + var(--font-boost,0px));margin-top:1px;flex:0 0 auto;}
.qObjText{color:rgba(255,255,255,.92);line-height:1.35;font-size:calc(14px + var(--font-boost,0px));font-weight:700;}
.qObj.isDone{opacity:.65;background:rgba(255,255,255,.03);}
.qObj.isDone .qObjMark{background:rgba(255,255,255,.10);color:rgba(255,255,255,.80);}
.qObj.isDone .qObjText{text-decoration:line-through;color:rgba(255,255,255,.75);}
.qObj.isCurrent{border-color:rgba(230,87,99,.45);background:rgba(230,87,99,.10);}
.qObj.isCurrent .qObjMark{background:rgba(230,87,99,.22);color:#e65763;}
.qObj.isCurrent .qObjText{color:rgba(255,255,255,.96);}
.qObj.isLocked{opacity:.50;filter:blur(2.6px);}
.qObj.isLocked .qObjMark{background:rgba(255,255,255,.10);color:rgba(255,255,255,.70);}
.qObj.isLocked .qObjText{color:rgba(255,255,255,.75);}
.qCharGrid{display:flex;flex-direction:column;gap:10px;padding:0 4px 10px 4px;overflow-y:auto;overflow-x:hidden;min-height:0;flex:1 1 auto;}
.qCharCard{display:flex;align-items:center;gap:14px;padding:10px 14px;border-radius:0 10px 10px 0;background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.10);cursor:pointer;user-select:none;position:relative;}
.qCharCard.isSelected{border-left:3px solid rgba(230,87,99,1);}
.qCharCardImgWrap{width:clamp(48px,6vw,60px);height:clamp(48px,6vw,60px);border-radius:8px;overflow:hidden;flex:0 0 auto;}
.qCharCardImg{width:100% !important;height:100% !important;min-width:unset !important;min-height:unset !important;max-width:unset !important;max-height:unset !important;object-fit:cover !important;display:block !important;border-radius:8px !important;}
.qCharCardInfo{display:flex;flex-direction:column;gap:3px;min-width:0;flex:1 1 auto;}
.qCharCardName{font-size:calc(14px + var(--font-boost,0px));font-weight:900;color:rgba(255,255,255,.96);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
.qCharCardRole{font-size:calc(14px + var(--font-boost,0px));font-weight:700;color:rgba(255,255,255,.75);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
.qCharCardPct{margin-left:auto;font-size:calc(16px + var(--font-boost,0px));font-weight:950;color:rgba(255,255,255,.92);white-space:nowrap;padding-left:10px;}
.qCharCardPctSym{font-size:calc(14px + var(--font-boost,0px));font-weight:700;color:rgba(255,255,255,.75);}
.qCharDetail{display:flex;flex-direction:column;}
.qCharDetailHeader{display:flex;align-items:center;gap:16px;margin-bottom:18px;margin-right:auto;flex-wrap:wrap;}
.qCharDetailImg{width:clamp(60px,8vw,90px) !important;min-width:clamp(60px,8vw,90px) !important;max-width:clamp(60px,8vw,90px) !important;height:clamp(60px,8vw,90px) !important;min-height:clamp(60px,8vw,90px) !important;max-height:clamp(60px,8vw,90px) !important;border-radius:10px !important;display:block !important;object-fit:cover !important;flex:0 0 auto !important;}
.qCharDetailHeaderInfo{display:flex;flex-direction:column;justify-content:center;gap:6px;min-width:0;}
.qCharDetailName{font-size:calc(18px + var(--font-boost,0px));font-weight:950;color:rgba(255,255,255,.98);line-height:1.05;}
.qCharDetailRole{font-size:calc(14px + var(--font-boost,0px));font-weight:900;letter-spacing:.12em;text-transform:uppercase;color:rgba(230,87,99,.95);}
.qCharDetailStats{display:flex;gap:10px;flex-wrap:wrap;padding:14px 0;border-top:1px solid rgba(255,255,255,.10);border-bottom:1px solid rgba(255,255,255,.10);margin-bottom:18px;}
.qCharStat{flex:1 1 80px;padding:10px 12px;border-radius:8px;background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.10);}
.qCharStatLabel{font-size:calc(14px + var(--font-boost,0px));font-weight:900;letter-spacing:.12em;text-transform:uppercase;color:rgba(255,255,255,.78);margin-bottom:4px;}
.qCharStatVal{font-size:calc(16px + var(--font-boost,0px));font-weight:950;color:rgba(255,255,255,.96);}
.qCharStatMax{font-size:calc(14px + var(--font-boost,0px));font-weight:700;color:rgba(255,255,255,.75);}
.qInstIcon{width:54px;height:54px;border-radius:8px;background:rgba(230,87,99,.15);border:1px solid rgba(230,87,99,.30);display:flex;align-items:center;justify-content:center;font-size:24px;flex:0 0 auto;}
.qInstLevelBar{margin-top:16px;padding:14px 16px;border-radius:10px;background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.10);}
.qInstLevelLabel{display:flex;align-items:center;justify-content:space-between;}
.qInstLevelTitle{font-size:calc(14px + var(--font-boost,0px));font-weight:900;letter-spacing:.12em;text-transform:uppercase;color:rgba(255,255,255,.85);}
.qInstLevelVal{font-size:calc(16px + var(--font-boost,0px));font-weight:950;color:#e65763;}
.qInstNpcList{display:flex;flex-direction:column;gap:8px;margin-top:8px;}
.qInstNpcRow{display:flex;align-items:center;gap:12px;padding:10px 14px;border-radius:10px;background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.10);cursor:pointer;transition:background 120ms,border-color 120ms;user-select:none;flex-wrap:wrap;}
.qInstNpcRow:hover{background:rgba(230,87,99,.10);border-color:rgba(230,87,99,.35);}
.qInstNpcLvl{font-size:calc(14px + var(--font-boost,0px));font-weight:900;color:rgba(255,255,255,.85);margin-left:auto;white-space:nowrap;}
.qInstNpcLvlVal{color:rgba(255,255,255,.96);}
.qInstNpcArrow{font-size:calc(16px + var(--font-boost,0px));color:rgba(230,87,99,.85);margin-left:8px;}
@media (max-width:900px){
.qUI{grid-template-columns:1fr;grid-template-rows:auto 1fr;overflow:auto;}
.qRight{min-height:300px;}
}
</style>// ------------------- CHAPTER 1 -------------------
// STEP 1
<<if $StartStoryMail == true>>
<<set $Story1_1Finish = true>>
<<set $Story1_1Current = false>>
<<set $Story1_2Current = true>>
<</if>>
// STEP 2 - OFF
<<if $StartStory == true>>
<<set $Story1_2Finish = true>>
<<set $Story1_2Current = false>>
<<set $Story2_1Current = true>>
<</if>>
// ------------------- CHAPTER 2 -------------------
// STEP 1
<<if $SearchWork == true>>
<<set $Story2_1Finish = true>>
<<set $Story2_1Current = false>>
<<set $Story2_2Current = true>>
<</if>>
// STEP 2
<<if $SearchWorkMailEnd == true>>
<<set $Story2_2Finish = true>>
<<set $Story2_2Current = false>>
<<set $Story2_3Current = true>>
<</if>>
// STEP 3
<<if $InterviewWorkArena == true>>
<<set $Story2_3Finish = true>>
<<set $Story2_3Current = false>>
<<set $Story3_1Current = true>>
<</if>>
// ------------------- CHAPTER 3 -------------------
// STEP 1
<<if $Reputation >= 50>>
<<set $Story3_1Finish = true>>
<<set $Story3_1Current = false>>
<<set $Story3_2Current = true>>
<</if>>
// STEP 2
<<if $TalkDealer1 == true>>
<<set $Story3_2Finish = true>>
<<set $Story3_2Current = false>>
<<set $Story3_3Current = true>>
<</if>>
// STEP 3
<<if $TalkDealer2 == true>>
<<set $Story3_3Finish = true>>
<<set $Story3_3Current = false>>
<<set $Story3_4Current = true>>
<</if>>
// STEP 4
<<if $TalkDealer3 == true>>
<<set $Story3_4Finish = true>>
<<set $Story3_4Current = false>>
<<set $Story4_1Current = true>>
<</if>>
// ------------------- CHAPTER 4 -------------------
// STEP 1
<<if $Inventory.spycam>>
<<set $Story4_1Finish = true>>
<<set $Story4_1Current = false>>
<<set $Story4_2Current = true>>
<</if>>
// STEP 2
<<if $Spycam.bathroom == true or $Spycam.housematemale == true or $Spycam.housematefemale == true or $Spycam.mainbedroom == true>>
<<set $SpycamStepStory = true>>
<</if>>
<<if $SpycamStepStory == true>>
<<set $Story4_2Finish = true>>
<<set $Story4_2Current = false>>
<<set $Story4_3Current = true>>
<</if>>
// STEP 3
<<if $SpycamSoftware == true>>
<<set $Story4_3Finish = true>>
<<set $Story4_3Current = false>>
<<set $Story4_4Current = true>>
<</if>>
// STEP 4
<<if $FirstEditingSpycam == true>>
<<set $Story4_4Finish = true>>
<<set $Story4_4Current = false>>
<<set $Story4_5Current = true>>
<</if>>
// STEP 5
<<if $FirstBoughtComponent == true>>
<<set $Story4_5Finish = true>>
<<set $Story4_5Current = false>>
<<set $Story5_1Current = true>>
// DELETE THIS WHEN CHAPTER 5 IS AVABLE
<<set $Story6_1Current = true>>
<</if>>
// ------------------- CHAPTER 5 -------------------
// WIP
// ------------------- CHAPTER 6 -------------------
// STEP 1
<<if $MayorStoryInfo1 == true>>
<<set $Story6_1Finish = true>>
<<set $Story6_1Current = false>>
<<set $Story6_2Current = true>>
<</if>>
// STEP 2
<<if $MayorStoryInfo2 == true>>
<<set $Story6_2Finish = true>>
<<set $Story6_2Current = false>>
<<set $Story6_3Current = true>>
<</if>>
// STEP 3
<<if $MayorStoryInfo4 == true>>
<<set $Story6_3Finish = true>>
<<set $Story6_3Current = false>>
<<set $Story6_4Current = true>>
<</if>>
// STEP 4
<<if $NPCMayor.lvl >= 3>>
<<set $Story6_4Finish = true>>
<<set $Story6_4Current = false>>
<<set $Story6_5Current = true>>
<</if>>
// STEP 5
<<if $MayorStoryInfo6 == true>>
<<set $Story6_5Finish = true>>
<<set $Story6_5Current = false>>
<<set $Story6_6Current = true>>
<</if>>
// STEP 6
<<if $MayorStoryInfo7 == true or $MayorStoryInfo8 == true>>
<<set $Story6_6Finish = true>>
<<set $Story6_6Current = false>>
<<set $Story6_7Current = true>>
<</if>>
// STEP 7
<<if $MayorStoryInfo9 == true>>
<<set $Story6_7Finish = true>>
<<set $Story6_7Current = false>>
<<set $Story6_8Current = true>>
<</if>>
// STEP 8
<<if $NPCMayor.lvl >= 4>>
<<set $Story6_8Finish = true>>
<<set $Story6_8Current = false>>
<<set $Story6_9Current = true>>
<</if>>
// STEP 9
<<if $MayorStoryInfo11 == true>>
<<set $Story6_9Finish = true>>
<<set $Story6_9Current = false>>
<<set $Story6_10Current = true>>
<</if>>
// STEP 10
<<if $MayorStoryInfo13 == true>>
<<set $Story6_10Finish = true>>
<<set $Story6_10Current = false>>
<<set $Story6_11Current = true>>
<</if>>
// STEP 11
<<if $NPCMayor.lvl >= 5>>
<<set $Story6_11Finish = true>>
<<set $Story6_11Current = false>>
<<set $Story6_12Current = true>>
<</if>>
// STEP 12
<<if $MayorStoryFinish == true>>
<<set $Story6_12Finish = true>>
<<set $Story6_12Current = false>>
<<set $Story7_1Current = true>>
<</if>><<bgpause>><div id="supportcredits-root"></div><<script>>
(function(){
function esc(s){return String(s==null?"":s).replace(/[&<>"']/g,function(c){return({"&":"&","<":"<",">":">",'"':""","'":"'"}[c]);});}
var data = {
supportTitle: "SUPPORT & CREDITS",
supportSub: "Join the community, support development, and meet the team behind the scenes.",
support: {
title: "Support Development",
desc: "Your support directly funds new features, assets, and late night coding sessions. Join our community to get exclusive sneak peeks and influence the roadmap.",
links: [
{
key: "patreon",
title: "Become a Patron",
sub: "Get Exclusive Rewards",
href: "https://www.patreon.com/cw/EnthrallGame",
accent: "#eebba3",
logo: "assets/support/logopatreon.png",
span: 1
},
{
key: "subscribestar",
title: "SubscribeStar.adult",
sub: "Support Uncensored Content And Get Exclusive Rewards",
href: "https://subscribestar.adult/EnthrallGame",
accent: "#ff4081",
logo: "assets/support/logosubscribestar.png",
span: 1
},
{
key: "discord",
title: "Discord Community",
sub: "Join The Community And Help Shape The Development By Sharing Your Ideas!",
href: "https://discord.com/invite/jSTjBKSjvm",
accent: "#5865f2",
logo: "assets/support/logodiscord.png",
span: 2
}
]
},
credits: {
title: "CREDITS",
groups: [
{
title: "CORE TEAM",
items: [
{ name: "Enthrall", desc: "GAME CREATOR" },
]
},
{
title: "CHARACTER ACTORS",
items: [
{ name: "Kenzie Reeves", desc: State.variables.NPCHousemateFemale.name + " the " + State.variables.NPCHousemateFemale.role },
{ name: "Ava Addams", desc: State.variables.NPCLandlady.name + " the " + State.variables.NPCLandlady.role },
{ name: "Lucie Wilde", desc: State.variables.NPCBestFriend.name + " the " + State.variables.NPCBestFriend.role },
{ name: "Skylar Vox", desc: State.variables.NPCMate1.name + " the " + State.variables.NPCMate1.role },
{ name: "Crystal Chase", desc: State.variables.NPCMate2.name + " the " + State.variables.NPCMate2.role },
{ name: "Gabbie Carter", desc: State.variables.NPCMate3.name + " the " + State.variables.NPCMate3.role },
{ name: "Lauren Phillips", desc: State.variables.NPCPrincipal.name + " the " + State.variables.NPCPrincipal.role },
{ name: "Chanel Preston", desc: State.variables.NPCMayor.name + " the " + State.variables.NPCMayor.role },
{ name: "NyNyLew", desc: "NyLust the Stripper 1" },
{ name: "Ami Bue", desc: "Ima Blue the Stripper 2" },
{ name: "Valerica Steele", desc: "Valeela the Stripper 3" },
{ name: "Joanna Angel", desc: "Angel the Stripper 3" },
]
},
{
title: "MASTER SUBSCRIBER",
items: [
{ name: "How to become one?", desc: "HAVE A SUBSCRIPTION AT THE [MASTER] TIER." },
]
},
]
}
};
function arrowSvg(){
return '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><path fill="rgb(255,255,255)" d="M256 144C256 131.1 263.8 119.5 275.8 114.6C287.8 109.6 301.6 112.3 310.8 121.4L470.8 281.4C483.3 293.9 483.3 314.2 470.8 326.7L310.8 486.7C301.6 495.8 287.8 498.5 275.8 493.4C263.8 488.5 256 476.9 256 464L256 144z"/></svg>';
}
function render(){
var root=document.getElementById("supportcredits-root");
if(!root) return;
var linksHtml = (data.support.links||[]).map(function(x){
var span = (+x.span===2) ? ' scSpan2' : '';
return ''+
'<a class="scLinkCard'+span+'" href="'+esc(x.href)+'" target="_blank" rel="noopener noreferrer" style="--accent:'+esc(x.accent)+'" data-sckey="'+esc(x.key)+'" tabindex="0">'+
'<div class="scLogoWrap" aria-hidden="true">'+
'<img class="scLogo" src="'+esc(x.logo)+'" alt="">'+
'</div>'+
'<div class="scTxt">'+
'<div class="scTitle">'+esc(x.title)+'</div>'+
'<div class="scSub">'+esc(x.sub)+'</div>'+
'</div>'+
'<div class="scRight">'+
'<div class="scArrow" aria-hidden="true">'+arrowSvg()+'</div>'+
'</div>'+
'</a>';
}).join("");
var creditsGroupsHtml = (data.credits.groups||[]).map(function(g){
var items=(g.items||[]).map(function(it){
return ''+
'<div class="scCredItem">'+
'<div class="scCredName">'+esc(it.name)+'</div>'+
'<div class="scCredDesc">'+esc(it.desc||"")+'</div>'+
'</div>';
}).join("");
return ''+
'<div class="scCredGroup">'+
'<div class="scCredGroupTitle">'+esc(g.title)+'</div>'+
'<div class="scCredList">'+items+'</div>'+
'</div>';
}).join("");
root.innerHTML =
'<div class="scPage">'+
'<div class="scTop">'+
'<div class="scTopTitle">'+esc(data.supportTitle)+'</div>'+
'<div class="scTopSub">'+esc(data.supportSub)+'</div>'+
'</div>'+
'<div class="scSection">'+
'<div class="scCard">'+
'<div class="scCardHead">'+
'<div class="scCardTitle">'+esc(data.support.title)+'</div>'+
'<div class="scCardDesc">'+esc(data.support.desc)+'</div>'+
'</div>'+
'<div class="scGrid">'+linksHtml+'</div>'+
'</div>'+
'</div>'+
'<div class="scSection">'+
'<div class="scCard">'+
'<div class="scCreditsTitle">'+esc(data.credits.title)+'</div>'+
'<div class="scCreditsBody">'+
'<div class="scCreditsGrid">'+creditsGroupsHtml+'</div>'+
'</div>'+
'</div>'+
'</div>'+
'</div>';
}
function bind(){
var root=document.getElementById("supportcredits-root");
if(!root) return;
$(root).on("click.sc", ".scLinkCard", function(ev){
ev.preventDefault();
var url = $(this).attr("href");
if(!url) return;
try {
if(typeof nw !== "undefined" && nw.Shell) {
nw.Shell.openExternal(url);
} else {
window.open(url, "_blank", "noopener,noreferrer");
}
} catch(e) {
window.open(url, "_blank", "noopener,noreferrer");
}
});
}
function initWhenReady(tries){
var root=document.getElementById("supportcredits-root");
if(!root){
if(tries>0) requestAnimationFrame(function(){initWhenReady(tries-1);});
return;
}
if(root.dataset.scInit==="1") return;
root.dataset.scInit="1";
render();
bind();
}
initWhenReady(120);
})();<</script>><style>
#supportcredits-root{width:100%;height:100%;}
#supportcredits-root *{box-sizing:border-box;}
.scPage{width:100%;min-height:100%;padding:clamp(18px,3vw,32px) clamp(18px,3vw,34px) clamp(18px,3vw,34px) clamp(18px,3vw,34px);}
.scTop{padding:8px 0 18px 0;}
.scTopTitle{font-size:clamp(22px,3vw,34px);font-weight:950;letter-spacing:.06em;text-transform:uppercase;color:rgba(255,255,255,.95);line-height:1.05;}
.scTopSub{margin-top:10px;color:rgba(255,255,255,.45);font-size:calc(14px + var(--font-boost,0px));line-height:1.55;max-width:860px;}
.scSection{margin-top:22px;}
.scCard{border-radius:14px;border:1px solid rgba(255,255,255,.10);background:rgba(255,255,255,.03);overflow:hidden;}
.scCardHead{padding:clamp(14px,2vw,22px);}
.scCardTitle{font-size:calc(18px + var(--font-boost,0px));font-weight:950;color:rgba(255,255,255,.92);}
.scCardDesc{margin-top:10px;font-size:calc(14px + var(--font-boost,0px));line-height:1.6;color:rgba(255,255,255,.42);max-width:980px;}
.scGrid{padding:16px clamp(14px,2vw,22px) 22px clamp(14px,2vw,22px);display:grid;grid-template-columns:1fr 1fr;gap:14px;}
.scSpan2{grid-column:1 / span 2;}
@media (max-width:980px){.scPage{padding:22px 18px 26px 18px;}.scGrid{grid-template-columns:1fr;}.scSpan2{grid-column:auto;}}
.scLinkCard{position:relative;display:flex;align-items:center;gap:clamp(10px,2vw,18px);padding:clamp(12px,2vw,18px);border-radius:12px;border:1px solid rgba(255,255,255,.10);background:rgba(0,0,0,.22);text-decoration:none;user-select:none;cursor:pointer;outline:none;min-height:74px;transition:transform .12s ease, border-color .12s ease, background .12s ease;}
.scLinkCard:focus-visible{outline:3px solid rgba(255,255,255,.25);outline-offset:3px;}
.scLinkCard:hover{transform:translateY(-1px);border-color:color-mix(in srgb, var(--accent) 55%, rgba(255,255,255,.18));background:color-mix(in srgb, rgba(255,255,255,.06) 68%, var(--accent));}
.scTxt{min-width:0;flex:1 1 auto;}
.scTitle{font-size:calc(14px + var(--font-boost,0px));font-weight:950;letter-spacing:.02em;color:rgba(255,255,255,.90);}
.scSub{margin-top:4px;font-size:calc(14px + var(--font-boost,0px));color:rgba(255,255,255,.50);}
.scRight{display:flex;align-items:center;gap:12px;flex:0 0 auto;}
.scLogoWrap{width:34px;height:34px;border-radius:999px;border:1px solid rgba(255,255,255,.12);background:rgba(255,255,255,.04);display:flex;align-items:center;justify-content:center;overflow:hidden;flex:0 0 auto;}
.scLogo{max-width:34px !important;min-width:34px !important;max-height:34px !important;min-height:34px !important;object-fit:contain !important;display:block !important;pointer-events:none !important;opacity:.95 !important;}
.scArrow{width:22px;height:22px;display:flex;align-items:center;justify-content:center;opacity:0;transform:translateX(-6px);transition:opacity .12s ease, transform .12s ease;flex:0 0 auto;}
.scArrow svg{width:18px;height:18px;opacity:.9;}
.scLinkCard:hover .scArrow{opacity:1;transform:translateX(0);}
.scCreditsTitle{padding:clamp(14px,2vw,22px) clamp(14px,2vw,22px) 16px clamp(14px,2vw,22px);font-size:calc(14px + var(--font-boost,0px));font-weight:950;letter-spacing:.22em;text-transform:uppercase;color:rgba(255,255,255,.92);}
.scCreditsBody{padding:0 clamp(14px,2vw,22px) 26px clamp(14px,2vw,22px);}
.scCreditsGrid{display:grid;grid-template-columns:repeat(4, minmax(180px, 1fr));gap:18px 22px;align-items:start;}
@media (max-width:1200px){.scCreditsGrid{grid-template-columns:repeat(3, minmax(180px, 1fr));}}
@media (max-width:980px){.scCreditsGrid{grid-template-columns:repeat(2, minmax(180px, 1fr));}}
@media (max-width:640px){.scCreditsGrid{grid-template-columns:1fr;}}
.scCredGroup{padding:clamp(12px,2vw,18px) clamp(12px,2vw,16px);border-radius:12px;border:1px solid rgba(255,255,255,.08);background:rgba(0,0,0,.22);min-height:220px;}
.scCredGroupTitle{font-size:calc(14px + var(--font-boost,0px));font-weight:950;letter-spacing:.22em;text-transform:uppercase;color:rgba(230,87,99,.95);margin:0 0 14px 0;}
.scCredList{display:flex;flex-direction:column;gap:20px;}
.scCredItem{min-width:0;}
.scCredName{font-size:calc(14px + var(--font-boost,0px));font-weight:600;color:rgba(255,255,255,.92);}
.scCredDesc{margin-top:5px;font-size:calc(14px + var(--font-boost,0px));font-weight:400;letter-spacing:.18em;text-transform:uppercase;color:rgba(255,255,255,.40);line-height:1.4;}
</style><<sound "music" "music.music" true>><<set _raw = $ActiveNPC>><<if !_raw or _raw.id is undefined>>Invalid NPC.<<else>><<set _id = String(_raw.id)>><<set _key = "NPC" + _id>><<run State.temporary.npcObj = State.variables[State.temporary.key] || State.variables[_key]>><<set _npc = _npcObj>><<set _imgBase = "assets/img/character/" + _id + "/grope/">><<set _gotoNpc = _npc.id + ".interact">><<if _npc.lvl == 0>><<TalkNPC _npc "What the hell are you doing?! Get off me!">>
<<elseif _npc.lvl >= 1>><<set _r = random(1, 5)>><<set _num = ('0' + _r).slice(-2)>><<set _webp = _imgBase + _num + ".webp">><<set _gif = _imgBase + _num + ".gif">><<print '<img src="' + _webp + '" onerror="this.onerror=null;this.src=\'' + _gif + '\';" style="object-fit:contain;display:block;margin:0 auto .5rem auto;">'>><<passagebg _webp _gif>><</passagebg>>
<<TalkNPC _npc "<em>...Mmmmmh...</em>">>
<div class="BottomUiBarCustom">
<<BottomButton "Action">><<link "🔄 Keep going">><<set $Hour++>><<Refresh>><</link>><</BottomButton>>
<<BottomButton "Move">><<link "↩️ Return">><<set $Hour++>><<goto _gotoNpc>><</link>><</BottomButton>>
</div>
<</if>><</if>><<sound "music" "music.music" true>><<set _raw = $ActiveNPC>><<if !_raw or _raw.id is undefined>>Invalid NPC.<<else>><<set _id = String(_raw.id)>><<set _key = "NPC" + _id>><<run State.temporary.npcObj = State.variables[State.temporary.key] || State.variables[_key]>><<set _npc = _npcObj>><<set _imgBase = "assets/img/character/" + _id + "/handjob/">><<set _gotoNpc = _npc.id + ".interact">><<if _npc.lvl == 0>><<TalkNPC _npc "What the hell are you doing?! Get off me!">>
<<elseif _npc.lvl >= 1>><<set _r = random(1, 5)>><<set _num = ('0' + _r).slice(-2)>><<set _webp = _imgBase + _num + ".webp">><<set _gif = _imgBase + _num + ".gif">><<print '<img src="' + _webp + '" onerror="this.onerror=null;this.src=\'' + _gif + '\';" style="object-fit:contain;display:block;margin:0 auto .5rem auto;">'>><<passagebg _webp _gif>><</passagebg>>
<<TalkNPC _npc "<em>...Mmmmmh...</em>">>
<div class="BottomUiBarCustom">
<<BottomButton "Action">><<link "🔄 Keep going">><<set $Hour++>><<Refresh>><</link>><</BottomButton>>
<<BottomButton "Move">><<link "↩️ Return">><<set $Hour++>><<goto _gotoNpc>><</link>><</BottomButton>>
</div>
<</if>><</if>><<sound "music" "music.music" true>><<set _raw = $ActiveNPC>><<if !_raw or _raw.id is undefined>>Invalid NPC.<<else>><<set _id = String(_raw.id)>><<set _key = "NPC" + _id>><<run State.temporary.npcObj = State.variables[State.temporary.key] || State.variables[_key]>><<set _npc = _npcObj>><<set _imgBase = "assets/img/character/" + _id + "/blowjob/">><<set _gotoNpc = _npc.id + ".interact">><<if _npc.lvl == 0>><<TalkNPC _npc "What the hell are you doing?! Get off me!">>
<<elseif _npc.lvl >= 1>><<set _r = random(1, 5)>><<set _num = ('0' + _r).slice(-2)>><<set _webp = _imgBase + _num + ".webp">><<set _gif = _imgBase + _num + ".gif">><<print '<img src="' + _webp + '" onerror="this.onerror=null;this.src=\'' + _gif + '\';" style="object-fit:contain;display:block;margin:0 auto .5rem auto;">'>><<passagebg _webp _gif>><</passagebg>>
<<TalkNPC _npc "<em>...Mmmmmh...</em>">>
<div class="BottomUiBarCustom">
<<BottomButton "Action">><<link "🔄 Keep going">><<set $Hour++>><<Refresh>><</link>><</BottomButton>>
<<BottomButton "Move">><<link "↩️ Return">><<set $Hour++>><<goto _gotoNpc>><</link>><</BottomButton>>
</div>
<</if>><</if>><<sound "music" "music.music" true>><<set _raw = $ActiveNPC>><<if !_raw or _raw.id is undefined>>Invalid NPC.<<else>><<set _id = String(_raw.id)>><<set _key = "NPC" + _id>><<run State.temporary.npcObj = State.variables[State.temporary.key] || State.variables[_key]>><<set _npc = _npcObj>><<set _imgBase = "assets/img/character/" + _id + "/pussy/">><<set _gotoNpc = _npc.id + ".interact">><<if _npc.lvl == 0>><<TalkNPC _npc "What the hell are you doing?! Get off me!">>
<<elseif _npc.lvl >= 1>><<set _r = random(1, 5)>><<set _num = ('0' + _r).slice(-2)>><<set _webp = _imgBase + _num + ".webp">><<set _gif = _imgBase + _num + ".gif">><<print '<img src="' + _webp + '" onerror="this.onerror=null;this.src=\'' + _gif + '\';" style="object-fit:contain;display:block;margin:0 auto .5rem auto;">'>><<passagebg _webp _gif>><</passagebg>>
<<TalkNPC _npc "<em>...Mmmmmh...</em>">>
<div class="BottomUiBarCustom">
<<BottomButton "Action">><<link "🔄 Keep going">><<set $Hour++>><<Refresh>><</link>><</BottomButton>>
<<BottomButton "Move">><<link "↩️ Return">><<set $Hour++>><<goto _gotoNpc>><</link>><</BottomButton>>
</div>
<</if>><</if>><<sound "music" "music.music" true>><<set _raw = $ActiveNPC>><<if !_raw or _raw.id is undefined>>Invalid NPC.<<else>><<set _id = String(_raw.id)>><<set _key = "NPC" + _id>><<run State.temporary.npcObj = State.variables[State.temporary.key] || State.variables[_key]>><<set _npc = _npcObj>><<set _imgBase = "assets/img/character/" + _id + "/anal/">><<set _gotoNpc = _npc.id + ".interact">><<if _npc.lvl == 0>><<TalkNPC _npc "What the hell are you doing?! Get off me!">>
<<elseif _npc.lvl >= 1>><<set _r = random(1, 5)>><<set _num = ('0' + _r).slice(-2)>><<set _webp = _imgBase + _num + ".webp">><<set _gif = _imgBase + _num + ".gif">><<print '<img src="' + _webp + '" onerror="this.onerror=null;this.src=\'' + _gif + '\';" style="object-fit:contain;display:block;margin:0 auto .5rem auto;">'>><<passagebg _webp _gif>><</passagebg>>
<<TalkNPC _npc "<em>...Mmmmmh...</em>">>
<div class="BottomUiBarCustom">
<<BottomButton "Action">><<link "🔄 Keep going">><<set $Hour++>><<Refresh>><</link>><</BottomButton>>
<<BottomButton "Move">><<link "↩️ Return">><<set $Hour++>><<goto _gotoNpc>><</link>><</BottomButton>>
</div>
<</if>><</if>><<sound "music" "music.music" true>><<set _raw = $ActiveNPC>><<if !_raw or _raw.id is undefined>>Invalid NPC.<<else>><<set _id = String(_raw.id)>><<set _key = "NPC" + _id>><<run State.temporary.npcObj = State.variables[State.temporary.key] || State.variables[_key]>><<set _npc = _npcObj>><<set _gotoNpc = _npc.id + ".interact">><<Gift _npc>><</if>>
<div class="BottomUiBarCustom">
<<BottomButton "Move">><<link "↩️ Return">><<goto _gotoNpc>><</link>><</BottomButton>>
</div><<bgpause>><div id="optui-root"></div><<script>>
(function(){
function esc(s){return String(s==null?"":s).replace(/[&<>"']/g,function(c){return({"&":"&","<":"<",">":">",'"':""","'":"'"}[c]);});}
function getVar(path){try{var V=State.variables;if(!path) return undefined;if(path[0]==="$") path=path.slice(1);var parts=path.split(".");var cur=V;for(var i=0;i<parts.length;i++){if(cur==null) return undefined;cur=cur[parts[i]];}return cur;}catch(e){return undefined;}}
function setVar(path,value){var V=State.variables;if(path[0]==="$") path=path.slice(1);var parts=path.split(".");var cur=V;for(var i=0;i<parts.length-1;i++){var k=parts[i];if(cur[k]==null||typeof cur[k]!=="object") cur[k]={};cur=cur[k];}cur[parts[parts.length-1]]=value;}
function clamp01(v){v=+v||0;return v<0?0:(v>1?1:v);}
function pct(v){return Math.round(clamp01(v)*100);}
function resetScroll(){try{window.scrollTo(0,0);}catch(e){}try{document.documentElement.scrollTop=0;}catch(e){}try{document.body.scrollTop=0;}catch(e){}try{var hb=document.getElementById("hubpass-body");if(hb) hb.scrollTop=0;}catch(e){}}
var OPTS_KEY="sc_options_v1";
function saveGameplayOptions(){try{var V=State.variables;var obj={};for(var k in V){if(k.indexOf("Opt")===0){obj[k]=V[k];}}localStorage.setItem(OPTS_KEY,JSON.stringify(obj));}catch(e){}}
function loadGameplayOptions(){
try{
var raw=localStorage.getItem(OPTS_KEY);
if(!raw) return;
var obj=JSON.parse(raw);
if(!obj||typeof obj!=="object") return;
var V=State.variables;
for(var k in obj){
if(k.indexOf("Opt")===0){
V[k]=obj[k];
}
}
if(typeof obj.OptFontSize!=="undefined"&&obj.OptFontSize!==0){
setTimeout(function(){if(window.applyGlobalFontSize) window.applyGlobalFontSize();},200);
}
}catch(e){}
}
function applyFontSize(offset){
var styleId='optui-font-override';
var existing=document.getElementById(styleId);
if(existing) existing.remove();
if(offset===0) return;
var elements=document.querySelectorAll('*');
var seen={};
var rules=[];
elements.forEach(function(el){
var cs=window.getComputedStyle(el);
var computed=parseFloat(cs.fontSize);
var weight=parseInt(cs.fontWeight,10)||400;
var maxPx;
if(weight<=500) maxPx=14;
else if(weight<=700) maxPx=12;
else maxPx=10;
if(computed<1||computed>maxPx) return;
var classes=Array.from(el.classList);
if(classes.length===0) return;
classes.forEach(function(cls){
if(seen[cls]) return;
seen[cls]=true;
rules.push('.'+cls+'{ font-size:'+(computed+offset)+'px !important; }');
});
});
if(rules.length===0) return;
var style=document.createElement('style');
style.id=styleId;
style.textContent=rules.join('\n');
document.head.appendChild(style);
}
function svg(name){var s={audio:'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><path fill="rgb(255, 255, 255)" d="M533.6 96.5C523.3 88.1 508.2 89.7 499.8 100C491.4 110.3 493 125.4 503.3 133.8C557.5 177.8 592 244.8 592 320C592 395.2 557.5 462.2 503.3 506.3C493 514.7 491.5 529.8 499.8 540.1C508.1 550.4 523.3 551.9 533.6 543.6C598.5 490.7 640 410.2 640 320C640 229.8 598.5 149.2 533.6 96.5zM473.1 171C462.8 162.6 447.7 164.2 439.3 174.5C430.9 184.8 432.5 199.9 442.8 208.3C475.3 234.7 496 274.9 496 320C496 365.1 475.3 405.3 442.8 431.8C432.5 440.2 431 455.3 439.3 465.6C447.6 475.9 462.8 477.4 473.1 469.1C516.3 433.9 544 380.2 544 320.1C544 260 516.3 206.3 473.1 171.1zM412.6 245.5C402.3 237.1 387.2 238.7 378.8 249C370.4 259.3 372 274.4 382.3 282.8C393.1 291.6 400 305 400 320C400 335 393.1 348.4 382.3 357.3C372 365.7 370.5 380.8 378.8 391.1C387.1 401.4 402.3 402.9 412.6 394.6C434.1 376.9 448 350.1 448 320C448 289.9 434.1 263.1 412.6 245.5zM80 416L128 416L262.1 535.2C268.5 540.9 276.7 544 285.2 544C304.4 544 320 528.4 320 509.2L320 130.8C320 111.6 304.4 96 285.2 96C276.7 96 268.5 99.1 262.1 104.8L128 224L80 224C53.5 224 32 245.5 32 272L32 368C32 394.5 53.5 416 80 416z"/></svg>',gameplay:'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><path fill="rgb(255, 255, 255)" d="M448 128C554 128 640 214 640 320C640 426 554 512 448 512L192 512C86 512 0 426 0 320C0 214 86 128 192 128L448 128zM192 240C178.7 240 168 250.7 168 264L168 296L136 296C122.7 296 112 306.7 112 320C112 333.3 122.7 344 136 344L168 344L168 376C168 389.3 178.7 400 192 400C205.3 400 216 389.3 216 376L216 344L248 344C261.3 344 272 333.3 272 320C272 306.7 261.3 296 248 296L216 296L216 264C216 250.7 205.3 240 192 240zM432 336C414.3 336 400 350.3 400 368C400 385.7 414.3 400 432 400C449.7 400 464 385.7 464 368C464 350.3 449.7 336 432 336zM496 240C478.3 240 464 254.3 464 272C464 289.7 478.3 304 496 304C513.7 304 528 289.7 528 272C528 254.3 513.7 240 496 240z"/></svg>',arrow:'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><path fill="rgb(255,255,255)" d="M256 144C256 131.1 263.8 119.5 275.8 114.6C287.8 109.6 301.6 112.3 310.8 121.4L470.8 281.4C483.3 293.9 483.3 314.2 470.8 326.7L310.8 486.7C301.6 495.8 287.8 498.5 275.8 493.4C263.8 488.5 256 476.9 256 464L256 144z"/></svg>'};return s[name]||"";}
function ensureDefaults(){var V=State.variables;loadGameplayOptions();if(typeof V.OptAllowGay==="undefined") V.OptAllowGay=true;if(typeof V.OptAllowFuta==="undefined") V.OptAllowFuta=true;if(typeof V.OptLanguage==="undefined") V.OptLanguage="English";if(typeof V.OptSkipMiniGamesOn==="undefined") V.OptSkipMiniGamesOn=false;if(typeof V.OptFontSize==="undefined") V.OptFontSize=0;if(typeof V.OptWindowMode==="undefined") V.OptWindowMode="fullscreen";}
function getMixer(){try{return (window.setup&&setup.AudioMixer)?setup.AudioMixer:(window.AudioMixer?window.AudioMixer:null)}catch(e){return window.AudioMixer||null}}
function initAudio(box){
if(!box) return;
if(box.getAttribute("data-opt-init")==="1") return;
box.setAttribute("data-opt-init","1");
var KEY="sc_audio_bus_v1";
function setText(bus,p){var el=box.querySelector('[data-val="'+bus+'"]');if(el) el.textContent=String(p|0)+"%";}
function setSlider(bus,p){var inp=box.querySelector('input[type="range"][data-bus="'+bus+'"]');if(inp) inp.value=String(p|0);}
function loadStore(){try{var raw=localStorage.getItem(KEY);if(!raw) return null;var obj=JSON.parse(raw);return obj&&typeof obj==="object"?obj:null}catch(e){return null}}
function saveStore(obj){try{localStorage.setItem(KEY,JSON.stringify(obj))}catch(e){}}
function forceApplyLive(m){try{if(m&&m.pools&&typeof m._mixVol==="function"){for(var sid in m.pools){var arr=m.pools[sid];if(!arr)continue;for(var i=0;i<arr.length;i++){var a=arr[i];if(!a||!a.__mixer)continue;a.volume=clamp01(m._mixVol(a.__mixer.bus));}}}}catch(e){}try{if(m&&m.playlistState&&typeof m._mixVol==="function"){for(var bus in m.playlistState){var st=m.playlistState[bus];if(!st||!st.audio)continue;var g=(typeof st.gain==="number")?st.gain:1;st.audio.volume=clamp01(m._mixVol(st.bus)*g);st.fading=false;}}}catch(e){}try{if(window.setup&&setup.refreshVideoBus)setup.refreshVideoBus()}catch(e){}}
function apply(bus,val01,opts){opts=opts||{};var m=getMixer();var v=clamp01(val01);var p=pct(v);setSlider(bus,p);setText(bus,p);try{var row=box.querySelector('.oAudioRow[data-row="'+bus+'"]');if(row){var fill=row.querySelector(".oFill");if(fill) fill.style.width=p+"%";}}catch(e){}if(m&&typeof m.setVolume==="function") m.setVolume(bus,v);forceApplyLive(m);if(!opts.noStore){var st=loadStore()||{};st[bus]=v;saveStore(st);}}
function defaults(){return {master:1,ui:1,music:0.15,bg:0.25,sfx:1,video:0.1};}
function readInit(){var m=getMixer();var out=defaults();var st=loadStore();if(st){for(var k in out){if(typeof st[k]==="number")out[k]=clamp01(st[k])}}if(m&&typeof m.getVolume==="function"){for(var k2 in out){try{var mv=m.getVolume(k2);if(typeof mv==="number") out[k2]=clamp01(mv);}catch(e){}}}return out;}
function applyAll(obj,opts){for(var k in obj)apply(k,obj[k],opts)}
function bind(bus){var inp=box.querySelector('input[type="range"][data-bus="'+bus+'"]');if(!inp) return;inp.addEventListener("input",function(){apply(bus,(+inp.value||0)/100)});inp.addEventListener("change",function(){apply(bus,(+inp.value||0)/100)});}
var init=readInit();applyAll(init,{noStore:true});saveStore(init);
["master","ui","music","bg","sfx","video"].forEach(bind);
box.addEventListener("click",function(ev){var b=ev.target&&ev.target.getAttribute?ev.target.getAttribute("data-test"):null;if(!b) return;var m=getMixer();if(!m) return;if(b==="ui"){m.play("ui","sfx.test")}else if(b==="music"){m.play("music","mainmenu",true)}else if(b==="bg"){m.playPlaylist("bg","sfx.test",false)}else if(b==="sfx"){m.play("sfx","sfx.test")}else if(b==="video"){m.play("video","sfx.test")}});
var resetBtn=document.getElementById("optSoundReset");
if(resetBtn) resetBtn.addEventListener("click",function(){var d=defaults();applyAll(d,{noStore:false});});
}
function render(root,state){
var navItems=[{key:"audio",label:"Audio",icon:"audio"},{key:"gameplay",label:"Gameplay",icon:"gameplay"}];
var leftHtml=navItems.map(function(it){var active=(state.tab===it.key)?" isActive":"";return '<div class="oNavItem'+active+'" data-otab="'+esc(it.key)+'"><div class="oNavIco">'+svg(it.icon)+'</div><div class="oNavLbl">'+esc(it.label)+'</div><div class="oNavArr">'+svg("arrow")+'</div></div>';}).join("");
var rightHtml="";
if(state.tab==="audio"){
rightHtml='<div class="oHead"><div class="oHeadIcon">'+svg("audio")+'</div><div class="oHeadTitle">AUDIO SETTINGS</div></div><div class="oDivider"></div><div class="oSectionSub">VOLUME LEVELS</div><div class="oAudioBox" id="optSoundBox">'+row("Master Volume","master","ui","100%")+row("UI Volume","ui","ui","100%")+row("Music Volume","music","music","20%")+row("Background Volume","bg","bg","75%")+row("SFX Volume","sfx","sfx","100%")+row("Voice Volume","video","video","20%")+'<div class="oAudioRow oAudioRowReset"><div class="oAudioLeft"><div class="oAudioName">Reset to default</div></div><div class="oAudioRight"><button class="oGhostBtn" type="button" id="optSoundReset">RESET TO DEFAULT</button></div></div></div>';
}else{
var gay=!!getVar("$OptAllowGay");
var futa=!!getVar("$OptAllowFuta");
var minigame=!!getVar("$OptSkipMiniGamesOn");
var lang=String(getVar("$OptLanguage")||"English");
var fontsize=parseInt(getVar("$OptFontSize")||0,10);
var pickOpenCls=state.langOpen?" isOpen":"";
var fontOptions=[{label:"Small",value:-2},{label:"Normal",value:0},{label:"Large",value:2},{label:"X-Large",value:4}];
rightHtml=
'<div class="oHead"><div class="oHeadIcon">'+svg("gameplay")+'</div><div class="oHeadTitle">GAMEPLAY SETTINGS</div></div><div class="oDivider"></div>'+
'<div class="oBlock" style="margin-top:0;padding-top:0;border-top:0;"><div class="oBlockTitle">DISPLAY</div>'+
'<div class="oRow"><div class="oRowLeft"><div class="oRowName">Text Size</div>'+
'<div class="oRowDesc" style="font-size:calc(12px + var(--font-boost,0px));">Adjust the size of small UI text elements across the entire game. Changes take effect on the next passage.</div></div>'+
'<div class="oRowRight" style="gap:6px;">'+fontOptions.map(function(opt){var active=(opt.value===fontsize)?' isActive':'';return '<button type="button" class="oFontBtn'+active+'" data-ofontsize="'+opt.value+'">'+esc(opt.label)+'</button>';}).join('')+'</div></div>'+
(window.electronAPI?(function(){var wm=String(getVar("$OptWindowMode")||"fullscreen");var wmOpts=[{label:"Fullscreen",value:"fullscreen"},{label:"Windowed",value:"windowed"},{label:"Maximized",value:"maximized"}];return '<div class="oRow"><div class="oRowLeft"><div class="oRowName">Window Mode</div><div class="oRowDesc" style="font-size:calc(12px + var(--font-boost,0px));">Switch between fullscreen, windowed, and maximized window.</div></div><div class="oRowRight" style="gap:6px;">'+wmOpts.map(function(opt){var active=(opt.value===wm)?' isActive':'';return '<button type="button" class="oFontBtn'+active+'" data-owm="'+opt.value+'">'+esc(opt.label)+'</button>';}).join('')+'</div></div>';})():'')+
'<div class="oBlock"><div class="oBlockTitle">INTERACTION</div>'+
'<div class="oRow"><div class="oRowLeft"><div class="oRowName">Homosexual Interactions</div><div class="oRowDesc">Enable or disable same-sex interactions.</div></div><div class="oRowRight"><button type="button" class="oToggle'+(gay?' isOn':'')+'" data-otoggle="gay" aria-pressed="'+(gay?'true':'false')+'"><span class="oKnob"></span></button></div></div>'+
'<div class="oRow"><div class="oRowLeft"><div class="oRowName">Futanari Interactions</div><div class="oRowDesc">Enable or disable futanari interactions.</div></div><div class="oRowRight"><button type="button" class="oToggle'+(futa?' isOn':'')+'" data-otoggle="futa" aria-pressed="'+(futa?'true':'false')+'"><span class="oKnob"></span></button></div></div>'+
'<div class="oRow"><div class="oRowLeft"><div class="oRowName">Disable Mini-games</div><div class="oRowDesc">If you want to disable mini-games, turn on the toggle.</div></div><div class="oRowRight"><button type="button" class="oToggle'+(minigame?' isOn':'')+'" data-otoggle="minigame" aria-pressed="'+(minigame?'true':'false')+'"><span class="oKnob"></span></button></div></div></div>'+
'<div class="oBlock"><div class="oBlockTitle">LANGUAGE</div>'+
'<div class="oRow"><div class="oRowLeft"><div class="oRowName">Game Language</div><div class="oRowDesc">Choose the language used by the UI and texts.</div></div>'+
'<div class="oRowRight"><button type="button" class="oPickBtn'+pickOpenCls+'" data-olang="1"><span class="oPickVal">'+esc(lang)+'</span><span class="oPickArr">'+svg("arrow")+'</span></button></div></div>'+
'<div class="oLangInfo">For translation requests, please ask on the official Discord. If you have a translation of the game, you can share it on the official Discord so it can be added officially.</div>'+
(state.langOpen?('<div class="oLangDrop" data-olangdrop="1">'+langItem("English",lang)+'<div class="oLangItem oLangCommunity" data-olangcommunity="1">➡️ Participate In Community Translation ⬅️</div></div>'):'')+
'</div>';
}
root.innerHTML='<div class="oUI"><div class="oLeft"><div class="oTitleWrap"><div class="oTitle">OPTIONS</div><div class="oSub">SYSTEM CONFIGURATION</div></div><div class="oNav">'+leftHtml+'</div></div><div class="oRight"><div class="oRightInner">'+rightHtml+'</div></div></div>';
var currentOffset=parseInt(getVar("$OptFontSize")||0,10);
document.documentElement.style.setProperty('--font-boost',currentOffset+'px');
function row(label,bus,testBus,mockPct){return '<div class="oAudioRow" data-row="'+esc(bus)+'"><div class="oAudioLeft"><div class="oAudioName">'+esc(label)+'</div></div><div class="oAudioMid"><input class="oRange" type="range" min="0" max="100" step="1" data-bus="'+esc(bus)+'"><div class="oTrack"><div class="oFill"><div class="oThumb"></div></div></div></div><div class="oAudioRight"><div class="oPct" data-val="'+esc(bus)+'">'+esc(mockPct)+'</div><button class="oTestBtn" type="button" data-test="'+esc(testBus)+'">TEST</button></div></div>';}
function langItem(name,current){var sel=(String(name)===String(current))?' isSel':'';var flags={"English":"gb","French":"fr","Spanish":"es","German":"de","Italian":"it","Portuguese":"pt","Russian":"ru","Japanese":"jp","Chinese":"cn"};var code=flags[name]||"";var flagHtml=code?'<img src="assets/flags/'+code+'.png" alt="" class="oLangFlagImg">':'';return '<div class="oLangItem'+sel+'" data-olangset="'+esc(name)+'"><div class="oLangItemRow"><div class="oLangItemDiv">'+flagHtml+'<span class="oLangItemName">'+esc(name)+'</span></div></div></div>';}
}
function bind(root,state){
$(root).off(".optui").on("click.optui",function(ev){
var t=ev.target;
var tab=t&&t.closest?t.closest("[data-otab]"):null;
if(tab){state.tab=tab.getAttribute("data-otab")||"audio";state.langOpen=false;render(root,state);resetScroll();if(state.tab==="audio") initAudio(document.getElementById("optSoundBox"));if(window.applyGlobalFontSize) window.applyGlobalFontSize();return;}
var fontBtn=t&&t.closest?t.closest("[data-ofontsize]"):null;
if(fontBtn){
var val=parseInt(fontBtn.getAttribute("data-ofontsize"),10);
setVar("$OptFontSize",val);
saveGameplayOptions();
document.documentElement.style.setProperty('--font-boost',val+'px');
render(root,state);
window.applyGlobalFontSize();
resetScroll();
return;
}
var wmBtn=t&&t.closest?t.closest("[data-owm]"):null;
if(wmBtn){
var wm=wmBtn.getAttribute("data-owm");
setVar("$OptWindowMode",wm);
saveGameplayOptions();
try{
if(wm==="fullscreen"){window.electronAPI.enterFullscreen();}
else if(wm==="windowed"){window.electronAPI.leaveFullscreen();window.electronAPI.restore();}
else if(wm==="maximized"){window.electronAPI.leaveFullscreen();window.electronAPI.maximize();}
}catch(e){}
render(root,state);
resetScroll();
return;
}
var tog=t&&t.closest?t.closest("[data-otoggle]"):null;
if(tog){var k=tog.getAttribute("data-otoggle");if(k==="gay") setVar("$OptAllowGay",!getVar("$OptAllowGay"));if(k==="futa") setVar("$OptAllowFuta",!getVar("$OptAllowFuta"));if(k==="minigame") setVar("$OptSkipMiniGamesOn",!getVar("$OptSkipMiniGamesOn"));saveGameplayOptions();render(root,state);resetScroll();return;}
var langBtn=t&&t.closest?t.closest("[data-olang]"):null;
if(langBtn){state.langOpen=!state.langOpen;render(root,state);return;}
var langSet=t&&t.closest?t.closest("[data-olangset]"):null;
if(langSet){var val2=langSet.getAttribute("data-olangset");setVar("$OptLanguage",val2);saveGameplayOptions();state.langOpen=false;render(root,state);return;}
var comm=t&&t.closest?t.closest("[data-olangcommunity]"):null;
if(comm){state.langOpen=false;render(root,state);try{if(window.setup&&setup.HubPass&&typeof setup.HubPass.renderBody==="function"){setup.HubPass.renderBody("SupportMenu");resetScroll();return;}if(window.setup&&typeof setup.openHubPass==="function"){setup.openHubPass("SupportMenu");return;}if(window.Engine&&typeof Engine.play==="function"){Engine.play("SupportMenu");return;}}catch(e){}return;}
});
$(root).off("input.optui").on("input.optui","input.oRange",function(ev){var inp=ev.target;var box=document.getElementById("optSoundBox");if(!box) return;var bus=inp.getAttribute("data-bus");if(!bus) return;var m=getMixer();var v=clamp01((+inp.value||0)/100);var p=pct(v);var valEl=box.querySelector('[data-val="'+bus+'"]');if(valEl) valEl.textContent=String(p|0)+"%";var row=inp.closest(".oAudioRow");if(row){var fill=row.querySelector(".oFill");if(fill) fill.style.width=p+"%";}try{if(m&&typeof m.setVolume==="function") m.setVolume(bus,v);}catch(e){}try{var KEY="sc_audio_bus_v1";var raw=localStorage.getItem(KEY);var st=raw?JSON.parse(raw):{};if(!st||typeof st!=="object") st={};st[bus]=v;localStorage.setItem(KEY,JSON.stringify(st));}catch(e){}});
$(root).off("change.optui").on("change.optui","input.oRange",function(){var box=document.getElementById("optSoundBox");if(box) initAudio(box);});
}
function initWhenReady(tries){
var root=document.getElementById("optui-root");
if(!root){if(tries>0) requestAnimationFrame(function(){initWhenReady(tries-1);});return;}
if(root.dataset.oInit==="1") return;
root.dataset.oInit="1";
ensureDefaults();
var state=State.variables._OptUIState||{tab:"audio",langOpen:false};
if(!state.tab) state.tab="audio";
State.variables._OptUIState=state;
render(root,state);
bind(root,state);
resetScroll();
if(state.tab==="audio") initAudio(document.getElementById("optSoundBox"));
var savedOffset=parseInt(getVar("$OptFontSize")||0,10);
document.documentElement.style.setProperty('--font-boost',savedOffset+'px');
if(savedOffset!==0) applyFontSize(savedOffset);
}
initWhenReady(120);
})();<</script>><style>
#optui-root{width:100%;height:100%;}
#optui-root *{box-sizing:border-box;}
.oUI{width:100%;height:100%;display:grid;grid-template-columns:clamp(220px,28%,360px) 1fr;gap:0;background:transparent;}
.oLeft{padding:26px 22px 18px 22px;border-right:1px solid rgba(255,255,255,.07);display:flex;flex-direction:column;min-height:0;}
.oTitleWrap{padding:6px 4px 18px 4px;}
.oTitle{font-size:clamp(22px,3vw,36px);font-weight:950;letter-spacing:.06em;color:rgba(255,255,255,.95);}
.oSub{margin-top:6px;font-size:calc(14px + var(--font-boost,0px));font-weight:900;letter-spacing:.18em;color:rgba(255,255,255,.35);text-transform:uppercase;}
.oNav{display:flex;flex-direction:column;gap:10px;padding:4px;flex:1 1 auto;min-height:0;}
.oNavItem{display:flex;align-items:center;gap:12px;padding:14px 14px;border-radius:10px;border:1px solid rgba(255,255,255,.08);background:rgba(255,255,255,.03);cursor:pointer;user-select:none;transition:background .18s ease,border-color .18s ease;}
.oNavItem:hover{background:rgba(255,255,255,.05);}
.oNavItem.isActive{border-color:rgba(230,87,99,.35);background:rgba(230,87,99,.06);}
.oNavIco{width:22px;height:22px;display:flex;align-items:center;justify-content:center;opacity:.9;}
.oNavIco svg{width:22px;height:22px;}
.oNavLbl{flex:1 1 auto;font-size:calc(14px + var(--font-boost,0px));font-weight:900;letter-spacing:.04em;color:rgba(255,255,255,.86);}
.oNavArr{width:16px;height:16px;opacity:.35;display:flex;align-items:center;justify-content:center;transition:opacity .18s ease;}
.oNavArr svg{width:16px;height:16px;}
.oNavItem.isActive .oNavArr{opacity:.7;}
.oRight{padding:24px clamp(18px,3vw,40px);min-height:0;overflow-y:auto;}
.oRightInner{width:100%;padding:0 4px;}
.oHead{display:flex;align-items:center;gap:12px;padding:6px 0 12px 0;}
.oHeadIcon{width:18px;height:18px;display:flex;align-items:center;justify-content:center;opacity:.9;}
.oHeadIcon svg{width:18px;height:18px;}
.oHeadTitle{font-size:calc(18px + var(--font-boost,0px));font-weight:950;letter-spacing:.10em;color:rgba(255,255,255,.90);text-transform:uppercase;}
.oDivider{height:1px;background:rgba(255,255,255,.08);margin:0 0 18px 0;}
.oSectionSub{font-size:calc(14px + var(--font-boost,0px));font-weight:900;letter-spacing:.14em;color:rgba(255,255,255,.35);text-transform:uppercase;margin:0 0 14px 0;}
.oAudioBox{display:flex;flex-direction:column;gap:18px;padding:6px 0 0 0;}
.oAudioRow{display:grid;grid-template-columns:clamp(140px,20%,220px) 1fr clamp(120px,14%,160px);gap:18px;align-items:center;}
.oAudioLeft{min-width:0;}
.oAudioName{font-size:calc(14px + var(--font-boost,0px));font-weight:900;color:rgba(255,255,255,.88);}
.oAudioMid{position:relative;min-width:0;height:26px;display:flex;align-items:center;}
.oRange{position:absolute;left:0;right:0;top:0;bottom:0;width:100%;height:100%;opacity:0;cursor:pointer;z-index:3;margin:0;padding:0;-webkit-appearance:none;appearance:none;}
.oTrack{width:100%;height:4px;border-radius:999px;background:rgba(255,255,255,.12);overflow:visible;position:relative;z-index:1;}
.oFill{height:100%;width:0%;background:rgba(230,87,99,.95);border-radius:999px;position:relative;transition:width .08s ease;}
.oThumb{position:absolute;right:-7px;top:50%;width:14px;height:14px;border-radius:999px;transform:translateY(-50%);background:rgba(230,87,99,.95);pointer-events:none;transition:transform .08s ease;}
.oAudioRight{display:flex;align-items:center;justify-content:flex-end;gap:12px;}
.oPct{min-width:52px;text-align:right;font-size:calc(14px + var(--font-boost,0px));font-weight:950;color:rgba(230,87,99,.95);letter-spacing:.06em;}
.oTestBtn{all:unset;padding:8px 10px;border-radius:10px;border:1px solid rgba(255,255,255,.10);background:rgba(255,255,255,.03);color:rgba(255,255,255,.70);font-weight:900;font-size:calc(14px + var(--font-boost,0px));letter-spacing:.12em;cursor:pointer;user-select:none;transition:background .15s ease,transform .1s ease;}
.oTestBtn:hover{background:rgba(255,255,255,.06);}
.oTestBtn:active{transform:translateY(1px);}
.oAudioRowReset{padding-top:18px;border-top:1px solid rgba(255,255,255,.08);margin-top:10px;}
.oGhostBtn{all:unset;width:100%;text-align:center;padding:12px 14px;border-radius:10px;border:1px solid rgba(255,255,255,.12);background:rgba(255,255,255,.03);color:rgba(255,255,255,.90);font-weight:950;letter-spacing:.12em;font-size:calc(14px + var(--font-boost,0px));cursor:pointer;user-select:none;transition:background .15s ease,transform .1s ease;}
.oGhostBtn:hover{background:rgba(255,255,255,.06);}
.oGhostBtn:active{transform:translateY(1px);}
.oBlock{margin-top:18px;padding-top:12px;border-top:1px solid rgba(255,255,255,.08);}
.oBlockTitle{font-size:calc(14px + var(--font-boost,0px));font-weight:950;letter-spacing:.14em;color:rgba(255,255,255,.45);text-transform:uppercase;margin-bottom:12px;}
.oRow{display:flex;align-items:center;justify-content:space-between;gap:18px;padding:10px 0;}
.oRowLeft{min-width:0;flex:1 1 auto;}
.oRowName{font-size:calc(14px + var(--font-boost,0px));font-weight:950;color:rgba(255,255,255,.88);}
.oRowDesc{margin-top:4px;font-size:calc(14px + var(--font-boost,0px));color:rgba(255,255,255,.42);}
.oRowRight{flex:0 0 auto;display:flex;align-items:center;gap:12px;}
.oToggle{all:unset;width:44px;height:24px;border-radius:999px;background:rgba(255,255,255,.10);border:1px solid rgba(255,255,255,.10);position:relative;cursor:pointer;transition:background .2s ease,border-color .2s ease;}
.oKnob{position:absolute;top:50%;left:3px;width:18px;height:18px;border-radius:999px;background:rgba(255,255,255,.55);transform:translateY(-50%);transition:transform .2s ease,background .2s ease;}
.oToggle.isOn{background:rgba(230,87,99,.18);border-color:rgba(230,87,99,.35);}
.oToggle.isOn .oKnob{transform:translateY(-50%) translateX(20px);background:rgba(230,87,99,.95);}
.oPickBtn{all:unset;display:inline-flex;align-items:center;gap:10px;padding:10px 12px;border-radius:10px;border:1px solid rgba(255,255,255,.12);background:rgba(255,255,255,.03);cursor:pointer;user-select:none;transition:background .15s ease,transform .1s ease;}
.oPickBtn:hover{background:rgba(255,255,255,.06);}
.oPickBtn:active{transform:translateY(1px);}
.oPickVal{font-size:calc(14px + var(--font-boost,0px));font-weight:950;letter-spacing:.10em;color:rgba(255,255,255,.86);}
.oPickArr{width:14px;height:14px;opacity:.55;display:flex;align-items:center;justify-content:center;transition:transform .18s ease,opacity .18s ease;}
.oPickArr svg{width:14px;height:14px;}
.oPickBtn.isOpen .oPickArr{transform:rotate(90deg);opacity:.85;}
.oLangInfo{margin-top:10px;color:rgba(255,255,255,.42);font-size:calc(14px + var(--font-boost,0px));line-height:1.45;}
.oLangDrop{margin-top:10px;border-radius:12px;border:1px solid rgba(255,255,255,.10);background:rgba(0,0,0,.35);overflow:hidden;}
.oLangCommunity{color:rgba(255,255,255,.85);}
.oFontBtn{all:unset;padding:8px 14px;border-radius:8px;border:1px solid rgba(255,255,255,.10);background:rgba(255,255,255,.03);color:rgba(255,255,255,.70);font-weight:900;font-size:calc(14px + var(--font-boost,0px));letter-spacing:.08em;cursor:pointer;user-select:none;transition:background .15s ease,border-color .15s ease,color .15s ease,transform .1s ease;}
.oFontBtn:hover{background:rgba(255,255,255,.06);}
.oFontBtn:active{transform:translateY(1px);}
.oFontBtn.isActive{background:rgba(230,87,99,.14);border-color:rgba(230,87,99,.40);color:rgba(230,87,99,.95);}
.oLangItem{font-weight:900;letter-spacing:.10em;font-size:calc(14px + var(--font-boost,0px));color:rgba(255,255,255,.78);cursor:pointer;user-select:none;border-top:1px solid rgba(255,255,255,.06);padding:0;height:50px !important;align-content:center;padding:0 20px 0 20px !important;transition:background .15s ease,color .15s ease;}
.oLangItem:first-child{border-top:0;}
.oLangItem:hover{background:rgba(255,255,255,.05);}
.oLangItem.isSel{background:rgba(230,87,99,.10);color:rgba(230,87,99,.95);}
.oLangItemRow{display:flex;flex-direction:row;align-items:center;justify-content:flex-start;gap:10px;}
.oLangItemDiv{display:flex;justify-content:flex-start;gap:10px;align-items:center;}
.oLangFlagImg{width:20px;height:15px;min-width:18px !important;max-width:18px !important;min-height:13px !important;max-height:13px !important;object-fit:cover;flex-shrink:0;display:block;border-radius:5px !important;}
.oLangItemName{flex-shrink:0;}
@media (max-width:980px){
.oUI{grid-template-columns:1fr;}
.oLeft{border-right:0;border-bottom:1px solid rgba(255,255,255,.07);}
.oAudioRow{grid-template-columns:1fr;gap:10px;}
.oAudioRight{justify-content:space-between;}
.oRight{padding:18px;}
}
</style><div class="hudTop">
<div class="hudStrip hudLeft">
<button type="button" id="hudHistBack" class="hudTile hudBtn" data-tip="Back" data-wikikey=""><span class="hudIcon hudArrow">←</span></button>
<button type="button" id="hudHistFwd" class="hudTile hudBtn" data-tip="Forward" data-wikikey=""><span class="hudIcon hudArrow">→</span></button>
<button type="button" id="hudCheat" class="hudTile hudBtn" data-tip="Cheat" data-wikikey="cheat" data-wiki="<<CheatMenu>>"><span class="hudIcon">🎲</span></button>
<button type="button" id="hudSupport" class="hudTile hudBtn" data-tip="Support" data-wikikey="support" data-wiki="<<SupportMenu>>"><span class="hudIcon">🛟</span></button>
</div>
<div class="hudStrip hudCenter">
<div class="hudTile hudDT" id="hud-time" data-tip="Day and Time" data-wikikey="time"><span class="hudIcon">📅</span><span class="hudText"><<if $Time == 0>>Morning<<elseif $Time == 1>>Noon<<elseif $Time == 2>>Afternoon<<elseif $Time == 3>>Night<<else>>...<</if>></span><span class="hudSep">•</span><span class="hudMini">Day</span><span class="hudNum"><<print $Day>></span></div>
<div class="hudTile" id="hud-energy" data-tip="Energy" data-wikikey="energy"><span class="hudIcon">⚡</span><span class="hudNum hudEnergy"><<print $Energy>></span></div>
<div class="hudTile" id="hud-heal" data-tip="Health" data-wikikey="health"><span class="hudIcon">❤️</span><span class="hudNum"><<print $Heal>></span></div>
<div class="hudTile" id="hud-stress" data-tip="Stress" data-wikikey="stress"><span class="hudIcon">😩</span><span class="hudNum hudStress"><<print $Stress>></span></div>
<div class="hudTile hudPPTile" id="hud-psychicpower" data-tip="Psychic Power" data-wikikey="psychicpower"><span class="hudIcon">🧠</span><span class="hudPPOrbs" id="hudPPOrbs"></span></div>
<div class="hudTile" id="hudCorruptionTile" data-tip="City Corruption" data-wikikey="corruption"><span class="hudIcon">💟</span><span class="hudNum"><<print $Corruption.city>></span></div>
<div class="hudTile" id="hud-reputation" data-tip="Reputation" data-wikikey="reputation"><span class="hudIcon">🎖️</span><span class="hudNum hudRep"><<print $Reputation>></span></div>
<div class="hudTile" id="hud-money" data-tip="Money" data-wikikey="money"><span class="hudIcon">💲</span><span class="hudNum"><<print $Money>></span></div>
<div class="hudTile" id="hud-bank" data-tip="Bank" data-wikikey="bank"><span class="hudIcon">🪙</span><span class="hudNum"><<print $Bank>></span></div>
<div class="hudTile" id="hud-fitness" data-tip="Fitness" data-wikikey="fitness"><span class="hudIcon">💪</span><span class="hudNum"><<print $Fitness>></span><<if $Fitness == $FitnessMax>><span class="hudTag">MAX</span><</if>></div>
</div>
<div class="hudStrip hudRight">
<button type="button" id="hudStory" class="hudTile hudBtn" data-tip="Story" data-wikikey="story" data-wiki="<<QuestStory>>"><span class="hudIcon">🧭</span></button>
<button type="button" id="hudPhone" class="hudTile hudBtn" data-tip="Phone" data-wikikey="phone"><span class="hudIcon">📱</span><span class="hudNotifDot" id="hudPhoneDot"></span></button>
<button type="button" id="hudWiki" class="hudTile hudBtn" data-tip="Encyclopedia" data-wikikey="wiki"><span class="hudIcon">📖</span></button>
<button type="button" id="hudBurger" class="hudTile hudBtn" data-tip="Menu" data-wikikey="menu"><span class="hudIcon hudBurgerIcon">☰</span><span class="hudNotifDot" id="hudAchDot"></span></button>
</div>
</div>
<style>
#ui-bar-history{display:none!important}
#top-ui-bar-inner .hudTop{position:relative;width:100%;height:auto;min-height:34px;display:flex;align-items:center;justify-content:space-between;gap:6px;flex-wrap:nowrap;}
#top-ui-bar-inner .hudStrip{display:flex;align-items:center;gap:clamp(3px,0.6vw,8px);white-space:nowrap;flex-shrink:0;}
#top-ui-bar-inner .hudLeft{flex-shrink:0;}
#top-ui-bar-inner .hudRight{flex-shrink:0;}
#top-ui-bar-inner .hudCenter{display:flex;align-items:center;justify-content:center;gap:clamp(3px,0.6vw,8px);flex:1 1 auto;min-width:0;overflow:hidden;flex-wrap:wrap;}
#top-ui-bar-inner .hudTile{display:inline-flex;align-items:center;justify-content:center;gap:clamp(4px,0.6vw,8px);height:clamp(28px,3.5vw,34px);padding:0 clamp(6px,1vw,10px);border-radius:10px;border:1px solid rgba(230,87,99,.0);background:rgba(255,255,255,.035);backdrop-filter:blur(6px);white-space:nowrap;flex:0 0 auto;min-width:0;transition:transform .12s ease,border-color .12s ease,background .12s ease;}
#top-ui-bar-inner .hudTile:hover{transform:translateY(-1px);border:1px solid rgba(230,87,99,.55);background:rgba(255,255,255,.055)}
#top-ui-bar-inner .hudBtn{cursor:pointer;width:clamp(28px,3.5vw,36px);padding:0;position:relative;flex-shrink:0;}
#top-ui-bar-inner .hudBtn[disabled]{opacity:.35;cursor:default;transform:none!important}
#top-ui-bar-inner .hudBtn[disabled]:hover{transform:none!important;border-color:rgba(230,87,99,.22)!important;background:rgba(255,255,255,.035)!important}
#top-ui-bar-inner .hudDT{gap:clamp(4px,0.8vw,10px);padding:0 clamp(6px,1vw,12px)}
#top-ui-bar-inner .hudIcon{font-size:clamp(12px,1.6vw,16px);line-height:1;display:inline-flex;align-items:center;justify-content:center;transform:translateY(.5px)}
#top-ui-bar-inner .hudArrow{color:#fff!important;font-weight:900!important;transform:translateY(0)}
#top-ui-bar-inner .hudBurgerIcon{color:#fff!important;font-weight:900!important}
#top-ui-bar-inner .hudText{font-size:calc(clamp(10px,1.2vw,13px) + var(--font-boost,0px));font-weight:800;letter-spacing:.2px;color:rgba(231,233,238,.95);line-height:1;display:inline-flex;align-items:center;transform:translateY(1px)}
#top-ui-bar-inner .hudMini{font-size:calc(clamp(9px,1.1vw,12px) + var(--font-boost,0px));font-weight:700;color:rgba(170,176,189,.9);line-height:1;display:inline-flex;align-items:center;transform:translateY(1px)}
#top-ui-bar-inner .hudNum{font-size:calc(clamp(10px,1.2vw,13px) + var(--font-boost,0px));font-weight:900;color:rgba(231,233,238,.98);line-height:1;display:inline-flex;align-items:center;transform:translateY(1px)}
#top-ui-bar-inner .hudSep{opacity:.35;transform:translateY(1px)}
#top-ui-bar-inner .hudTag{font-size:calc(clamp(8px,0.9vw,10px) + var(--font-boost,0px));font-weight:900;letter-spacing:.3px;opacity:.7;padding:2px 7px;border-radius:999px;border:1px solid rgba(255,255,255,.12);background:rgba(255,255,255,.04);transform:translateY(1px)}
#top-ui-bar-inner .hudEnergy{color:rgba(241, 196, 15,.95)}
#top-ui-bar-inner .hudStress{color:rgba(231,76,60,.95)}
#top-ui-bar-inner .hudPPTile{gap:clamp(3px,0.5vw,6px);padding:0 clamp(6px,1vw,10px);}
#top-ui-bar-inner .hudPPOrbs{display:inline-flex;align-items:center;gap:clamp(2px,0.4vw,4px);transform:translateY(1px);}
#top-ui-bar-inner .hudPPOrb{display:inline-block;width:clamp(7px,1vw,10px);height:clamp(7px,1vw,10px);border-radius:999px;transition:background .2s ease,box-shadow .2s ease;}
#top-ui-bar-inner .hudPPOrb--on{background:rgba(122,162,255,.95);box-shadow:0 0 6px rgba(122,162,255,.70);}
#top-ui-bar-inner .hudPPOrb--off{background:rgba(122,162,255,.18);box-shadow:none;}
#top-ui-bar-inner .hudRep{color:rgba(122,162,255,.95)}
#top-ui-bar-inner .hudMailHot{border-color:rgba(230,87,99,.70)!important;background:rgba(230,87,99,.35)!important;box-shadow:0 12px 26px rgba(230,87,99,.22)!important;}
#top-ui-bar-inner .hudMailHot:hover{background:rgba(230,87,99,.50)!important;border-color:rgba(230,87,99,.95)!important;}
#top-ui-bar-inner .hudNotifDot{position:absolute;top:-3px;right:-3px;width:9px;height:9px;border-radius:999px;background:#e65763;border:1.5px solid rgba(8,8,8,.90);display:none;box-shadow:0 0 8px rgba(230,87,99,.70);}
#top-ui-bar-inner .hudNotifDot.on{display:block;}
@media (max-width:900px){
#top-ui-bar-inner .hudDT .hudMini,
#top-ui-bar-inner .hudDT .hudSep{display:none;}
#top-ui-bar-inner .hudTag{display:none;}
}
@media (max-width:700px){
#top-ui-bar-inner .hudCenter{gap:2px;}
#top-ui-bar-inner .hudTile{padding:0 clamp(4px,0.8vw,8px);}
}
</style>
<<script>>
(function(){
function updatePPOrbs(){
requestAnimationFrame(function(){
var el=document.getElementById("hudPPOrbs");
if(!el) return;
var pp=State.variables.PsychicPower||0;
var max=State.variables.PsychicPowerMax||3;
var out="";
for(var i=0;i<max;i++){out+='<span class="hudPPOrb '+(i<pp?'hudPPOrb--on':'hudPPOrb--off')+'"></span>';}
el.innerHTML=out;
});
}
function updatePhoneDot(){
var dot=document.getElementById("hudPhoneDot");
if(!dot) return;
try{
var V=State.variables;
var hasMail=!!V.MailInBox;
var hasSms=V.SMSData&&Object.keys(V.SMSData).some(function(k){return V.SMSData[k].delivered&&!V.SMSData[k].read;});
if(hasMail||hasSms) dot.classList.add("on"); else dot.classList.remove("on");
}catch(e){}
}
if(setup._hudTopInitV9){ updatePPOrbs(); updatePhoneDot(); return; }
setup._hudTopInitV9=true;
var _hmx=0, _hmy=0;
document.addEventListener("mousemove",function(e){
_hmx=e.clientX; _hmy=e.clientY;
},true);
function hudClearAllTips(){
if(setup.wikiOpenTip && setup._hudClearFn) setup._hudClearFn();
}
function hudAttachTile($tile){
var wikiKey=($tile.attr("data-wikikey")||"").toLowerCase();
var tipLabel=$tile.data("tip")||"";
var isCorTile=$tile[0].id==="hudCorruptionTile";
var showTimer=null;
$tile.on("mouseenter",function(){
clearTimeout(showTimer);
showTimer=setTimeout(function(){
var r=$tile[0].getBoundingClientRect();
if(_hmx<r.left||_hmx>r.right||_hmy<r.top||_hmy>r.bottom) return;
if(isCorTile && setup.wikiOpenTip){
setup.wikiOpenTip("corruption", 0, $tile);
} else if(wikiKey && setup.wikiOpenTip && setup.wikiDefs && setup.wikiDefs[wikiKey]){
setup.wikiOpenTip(wikiKey, 0, $tile);
} else if(setup._hudFallbackTip){
setup._hudFallbackTip(tipLabel, $tile);
}
},300);
});
$tile.on("mouseleave",function(){
clearTimeout(showTimer);
});
}
setup._hudFallbackTip = (function(){
var LOCK_DELAY=1200;
var fallbackStack=[];
document.addEventListener("mousemove",function(){
var snapshot=fallbackStack.slice();
for(var i=snapshot.length-1;i>=0;i--){
var t=snapshot[i];
if(fallbackStack.indexOf(t)===-1) continue;
var r=t.$source[0].getBoundingClientRect();
var inSource=_hmx>=r.left&&_hmx<=r.right&&_hmy>=r.top&&_hmy<=r.bottom;
if(!t.locked){
if(!inSource){ t.$el.remove(); fallbackStack.splice(fallbackStack.indexOf(t),1); return; }
} else {
var tr=t.$el[0].getBoundingClientRect();
var inTip=_hmx>=tr.left&&_hmx<=tr.right&&_hmy>=tr.top&&_hmy<=tr.bottom;
if(!inTip&&!inSource){ t.$el.remove(); fallbackStack.splice(fallbackStack.indexOf(t),1); }
return;
}
}
},true);
return function(label,$tile){
fallbackStack.forEach(function(t){ clearTimeout(t.lockTimer); t.$el.remove(); });
fallbackStack=[];
var $tip=$("<div>").css({
position:"fixed", zIndex:999980, padding:"10px 14px", borderRadius:"10px",
background:"rgba(8,8,8,.96)", border:"2px solid rgba(230,87,99,.35)",
boxShadow:"0 8px 24px rgba(0,0,0,.6)", pointerEvents:"none",
fontFamily:"inherit", boxSizing:"border-box", whiteSpace:"nowrap",
fontWeight:"900", fontSize:"calc(13px + var(--font-boost,0px))",
color:"rgba(231,233,238,.98)", letterSpacing:".02em",
opacity:"0", transition:"opacity .20s ease, transform .20s ease",
transform:"translateY(4px)"
}).text(label);
$("body").append($tip);
var r=$tile[0].getBoundingClientRect();
var vw=window.innerWidth, vh=window.innerHeight, margin=10;
var tipW=$tip.outerWidth()||160, tipH=$tip.outerHeight()||40;
var x=r.left+(r.width/2)-(tipW/2);
var y=r.bottom+tipH+margin<vh?r.bottom:r.top-tipH;
x=Math.max(margin,Math.min(x,vw-tipW-margin));
y=Math.max(margin,Math.min(y,vh-tipH-margin));
$tip.css({left:x+"px",top:y+"px"});
requestAnimationFrame(function(){ $tip.css({opacity:"1",transform:"translateY(0)"}); });
var tipObj={$el:$tip,$source:$tile,locked:false,lockTimer:null};
fallbackStack.push(tipObj);
tipObj.lockTimer=setTimeout(function(){
if(fallbackStack.indexOf(tipObj)===-1) return;
tipObj.locked=true;
$tip.css({pointerEvents:"auto",borderColor:"rgba(230, 87, 99,.7)"});
},LOCK_DELAY);
};
})();
setup._hudClearFn = function(){
if(setup._hudFallbackClear) setup._hudFallbackClear();
};
jQuery(document).on(":passageend :passagerender",function(){
updateHistory();
updatePPOrbs();
updatePhoneDot();
setTimeout(function(){
$("#top-ui-bar-inner .hudTile[data-tip]").each(function(){
var $t=$(this);
if(!$t.data("_hudwiki_bound")){
$t.data("_hudwiki_bound",true);
hudAttachTile($t);
}
});
},50);
});
function byId(id){ return document.getElementById(id); }
function canUndo(){ try{ return typeof State!=="undefined"&&State.length>1; }catch(e){ return false; } }
function canRedo(){ try{ return typeof State!=="undefined"&&State.size>State.length; }catch(e){ return false; } }
function hasUnclaimedAchReward(){
try{
var V=State.variables;
if(V.CheatOn===true) return false;
var data=Array.isArray(V.Achievements)?V.Achievements:setup.AchievementsData();
for(var i=0;i<data.length;i++){
var a=data[i];
if(!a.reward||!a.reward.enabled) continue;
if(V["_AchRewarded_"+a.id]) continue;
var objs=a.objectives||[];
if(!objs.length) continue;
var allDone=true;
for(var j=0;j<objs.length;j++){
var o=objs[j];
if(o.type==="flag"){
var fk=String(o.finish||"").replace(/^\$/,"");
if(!V[fk]){allDone=false;break;}
}else{
var ck=String(o.current||"").replace(/^\$/,"");
var parts=ck.split(".");
var cur=V[parts[0]];
for(var p=1;p<parts.length;p++) cur=cur?cur[parts[p]]:undefined;
var n=Number(cur);
if(!Number.isFinite(n)||n<Number(o.target)){allDone=false;break;}
}
}
if(allDone) return true;
}
return false;
}catch(e){return false;}
}
function updateBadges(){
var dot=document.getElementById("hudAchDot");
if(dot){ if(hasUnclaimedAchReward()) dot.classList.add("on"); else dot.classList.remove("on"); }
}
function updateHistory(){
var b=byId("hudHistBack"); var f=byId("hudHistFwd");
if(b) b.disabled=!canUndo();
if(f) f.disabled=!canRedo();
updateBadges();
}
function afterNavRefresh(){ requestAnimationFrame(function(){ updateHistory(); updatePPOrbs(); updatePhoneDot(); }); }
function isPauseOpenNow(){
try{ var body=document.getElementById("ui-dialog-body"); return !!(body&&body.querySelector&&body.querySelector(".pauseMenu")); }catch(e){ return false; }
}
function togglePauseMenu(){
try{ if(typeof Dialog!=="undefined"&&Dialog.isOpen&&Dialog.isOpen()&&isPauseOpenNow()){ Dialog.close(); return; } }catch(e){}
try{ if(setup&&typeof setup.openPauseMenu==="function") setup.openPauseMenu(); }catch(e){}
}
function runWiki(wiki){ try{ if(!wiki) return; Wikifier.wikifyEval(String(wiki)); }catch(e){} }
document.addEventListener("click",function(e){
var btn=e.target&&e.target.closest?e.target.closest("#top-ui-bar-inner button.hudBtn"):null;
if(!btn) return;
if(btn.id==="hudPhone"){ e.preventDefault(); if(window.setup&&setup.Phone) setup.Phone.toggle(); return; }
if(btn.id==="hudHistBack"){ e.preventDefault(); try{ if(canUndo()&&typeof Engine!=="undefined"&&Engine.backward){ Engine.backward(); afterNavRefresh(); } }catch(err){} return; }
if(btn.id==="hudHistFwd"){ e.preventDefault(); try{ if(canRedo()&&typeof Engine!=="undefined"&&Engine.forward){ Engine.forward(); afterNavRefresh(); } }catch(err){} return; }
if(btn.id==="hudBurger"){ e.preventDefault(); e.stopPropagation(); togglePauseMenu(); return; }
if(btn.id==="hudWiki"){ e.preventDefault(); try{ Dialog&&Dialog.isOpen&&Dialog.isOpen()&&Dialog.close(); }catch(_){} if(setup.wikiOpenModal) setup.wikiOpenModal(); return; }
var wiki=btn.getAttribute("data-wiki");
if(wiki){ e.preventDefault(); try{ Dialog&&Dialog.isOpen&&Dialog.isOpen()&&Dialog.close(); }catch(_){} runWiki(wiki); return; }
},true);
setTimeout(function(){
$("#top-ui-bar-inner .hudTile[data-tip]").each(function(){
var $t=$(this);
if(!$t.data("_hudwiki_bound")){
$t.data("_hudwiki_bound",true);
hudAttachTile($t);
}
});
},100);
updateHistory();
updatePPOrbs();
updatePhoneDot();
})();
<</script>><<pauseguard true>><<sound "music" "music.main" true>><div class="mm4-root"><div class="mm4-bg"></div><div class="mm4-ui"><div class="mm4-main"><div class="mm4-header"><img class="mm4-logo" src="assets/logo.png" alt="Logo"></div><div class="mm4-menu"><<set $mmHasSave=false>><<script>>try{if(window.Save&&Save.browser&&typeof Save.browser.size==="number"){State.variables.mmHasSave=Save.browser.size>0;}else if(window.Save&&Save.slots&&typeof Save.slots.isEmpty==="function"){State.variables.mmHasSave=!Save.slots.isEmpty();}else if(window.Save&&Save.autosave&&typeof Save.autosave.has==="function"){State.variables.mmHasSave=Save.autosave.has();}else{State.variables.mmHasSave=false;}}catch(e){State.variables.mmHasSave=false;}<</script>><<if $mmHasSave>><button class="mm4-item mm4-continue" type="button" data-act="continue"><span class="mm4-label">CONTINUE</span><span class="mm4-desc">Resume last save</span></button><</if>><button class="mm4-item" type="button" data-act="new"><span class="mm4-label">NEW GAME</span><span class="mm4-desc">Start a new run</span></button><button class="mm4-item" type="button" data-act="load"><span class="mm4-label">LOAD</span><span class="mm4-desc">Select a save</span></button><button class="mm4-item" type="button" data-act="options"><span class="mm4-label">OPTIONS</span><span class="mm4-desc">Audio, video, gameplay</span></button><button class="mm4-item" type="button" data-wiki="<<SupportMenu>>"><span class="mm4-label">SUPPORT</span><span class="mm4-desc">Support Project</span></button><button class="mm4-item" type="button" data-act="galery"><span class="mm4-label">GALERY</span><span class="mm4-desc">Review all images and videos</span></button><button class="mm4-item" type="button" data-act="credits"><span class="mm4-label">CREDITS</span><span class="mm4-desc">Team & thanks</span></button><<if setup.isNW()>><button class="mm4-item mm4-danger" type="button" data-act="quit"><span class="mm4-label">QUIT GAME</span><span class="mm4-desc">Exit</span></button><</if>></div><div class="mm4-bottom"><div class="mm4-leftnote"><<print $GameVersion.name>></div></div></div><div class="mm4-updates" aria-label="Updates"><div class="mm4-upd-head"><div class="mm4-upd-title">UPDATES</div></div><div class="mm4-upd-body" id="mm4UpdBody"><details class="mm4-upd-item" open><summary class="mm4-upd-sum"><span class="mm4-upd-ver">No feed</span><span class="mm4-upd-datewrap"><span class="mm4-upd-date">—</span><span class="mm4-upd-arrow" aria-hidden="true"></span></span></summary><div class="mm4-upd-panel"><div class="mm4-upd-ttl"> </div><div class="mm4-upd-text">Set setup.mmUpdateUrl (JSON) to show updates.</div></div></details></div></div></div><div class="mm4-confirm" aria-hidden="true"><div class="mm4-confirm-backdrop"></div><div class="mm4-confirm-card" role="dialog" aria-modal="true" aria-label="Confirm"><div class="mm4-confirm-title">Warning</div><div class="mm4-confirm-msg"></div><div class="mm4-confirm-actions"><button class="mm4-cbtn" type="button" data-confirm="no">Cancel</button><button class="mm4-cbtn mm4-cbtn-danger" type="button" data-confirm="yes">Quit</button></div></div></div><<script>>
(function () {
"use strict";
function openConfirm(msg, onYes) {
var root = document.querySelector(".mm4-root");
if (!root) return;
var box = root.querySelector(".mm4-confirm");
if (!box) return;
box.setAttribute("aria-hidden", "false");
box.classList.add("is-open");
var m = root.querySelector(".mm4-confirm-msg");
if (m) m.textContent = String(msg);
box._onYes = onYes;
try { var b = root.querySelector('[data-confirm="no"]'); if (b) b.focus(); } catch (e) {}
}
function closeConfirm() {
var root = document.querySelector(".mm4-root");
if (!root) return;
var box = root.querySelector(".mm4-confirm");
if (!box) return;
box.setAttribute("aria-hidden", "true");
box.classList.remove("is-open");
box._onYes = null;
}
function doContinue(btn) {
try { btn && btn.classList.add("is-busy"); } catch (e) {}
try {
if (window.Save && Save.browser && typeof Save.browser.continue === "function") {
Save.browser.continue().catch(function (error) {
try { if (window.UI && UI.alert) UI.alert(error); else alert(String(error)); } catch (e) {}
}).finally(function () {
try { btn && btn.classList.remove("is-busy"); } catch (e) {}
});
return;
}
if (window.Save && Save.autosave && typeof Save.autosave.has === "function" && Save.autosave.has() && typeof Save.autosave.load === "function") {
Save.autosave.load();
return;
}
} catch (e) {}
try { btn && btn.classList.remove("is-busy"); } catch (e) {}
}
function doNew() {
try { Engine.play("Confirm 1"); } catch (e) {}
}
function doLoad() {
try { Wikifier.wikifyEval("<<SavesMenu>>"); } catch (e) {}
}
function doOptions() {
try { Wikifier.wikifyEval("<<OptionMenu>>"); } catch (e) {}
}
function doSupport() {
try { Wikifier.wikifyEval("<<SupportMenu>>"); } catch (e) {}
}
function doCredits() {
try { Wikifier.wikifyEval("<<CreditsMenu>>"); } catch (e) {}
}
function doGallery () {
try { Engine.play("Gallery "); } catch (e) {}
}
function doQuit() {
openConfirm("Quit the game?", function () {
try {
if (window.electronAPI) { window.electronAPI.quit(); }
} catch (e) {}
});
}
function updLinkify(s){
return s.replace(/(https?:\/\/[^\s<&]+)/g, function(url){
if(window.electronAPI){
return '<a href="#" onclick="window.electronAPI.openExternal(\''+url+'\');return false;" style="color:rgba(230,87,99,0.9);text-decoration:underline;">'+url+'</a>';
}
return '<a href="'+url+'" target="_blank" rel="noopener" style="color:rgba(230,87,99,0.9);text-decoration:underline;">'+url+'</a>';
});
}
function updEscape(s){return String(s||"").replace(/[&<>"]/g,function(c){return({"&":"&","<":"<",">":">",'"':"""}[c]);});}
function updRender(items){
var body=document.getElementById("mm4UpdBody");
var hint=document.getElementById("mm4UpdHint");
if(!body)return;
if(!items||!items.length){body.innerHTML='<details class="mm4-upd-item" open><summary class="mm4-upd-sum"><span class="mm4-upd-ver">No updates</span><span class="mm4-upd-datewrap"><span class="mm4-upd-date">—</span><span class="mm4-upd-arrow" aria-hidden="true"></span></span></summary><div class="mm4-upd-panel"><div class="mm4-upd-ttl"> </div><div class="mm4-upd-text"> </div></div></details>';if(hint)hint.textContent="";return;}
var max=4,html="";
for(var i=0;i<Math.min(max,items.length);i++){
var it=items[i]||{};
var ver=updEscape(it.version||it.ver||"");
var dat=updEscape(it.date||"");
var ttl=updEscape(it.title||"");
var txt=updLinkify(updEscape(it.body||it.text||"").replace(/\n/g,"<br>"));
var news=(i===0)?'<span class="mm4-upd-news">NEWS !</span>':"";
html+='<details class="mm4-upd-item" '+(i===0?'open':'')+'><summary class="mm4-upd-sum"><span class="mm4-upd-ver">'+ver+news+'</span><span class="mm4-upd-datewrap"><span class="mm4-upd-date">'+dat+'</span><span class="mm4-upd-arrow" aria-hidden="true"></span></span></summary><div class="mm4-upd-panel"><div class="mm4-upd-ttl">'+ttl+'</div><div class="mm4-upd-text">'+txt+'</div></div></details>';
}
body.innerHTML=html;
if(hint)hint.textContent=(items.length>max)?("+"+(items.length-max)+" more"):"";
setTimeout(function(){if(window.applyGlobalFontSize) window.applyGlobalFontSize();},50);
}
function updLoad(){
try{
var url="";
try{
if (setup && setup.mmUpdateUrl) url=String(setup.mmUpdateUrl);
else if (setup && setup.Changelog && setup.Changelog.url) url=String(setup.Changelog.url);
}catch(e){}
var cache=null;
try{
cache=(State&&State.variables)?(State.variables.mmUpdateCache||State.variables._changelogCache):null;
}catch(e){}
if(cache&&cache.items){updRender(cache.items);return;}
if(!url){updRender(null);return;}
fetch(url,{cache:"no-store"})
.then(function(r){if(!r.ok)throw new Error("HTTP "+r.status);return r.json();})
.then(function(j){
var items=(j&&j.items&&Array.isArray(j.items))?j.items.slice():[];
try{
if(State&&State.variables){
State.variables.mmUpdateCache={items:items,updatedAt:j.updatedAt||""};
State.variables._changelogCache={items:items,updatedAt:j.updatedAt||""};
}
}catch(e){}
updRender(items);
})
.catch(function(){
updRender(null);
});
}catch(e){updRender(null);}
}
$(document)
.off("click.mm4Main")
.on("click.mm4Main", ".mm4-root .mm4-menu .mm4-item", function (ev) {
ev.preventDefault();
ev.stopPropagation();
var act = this.getAttribute("data-act");
var wiki = this.getAttribute("data-wiki");
if (act === "continue") { doContinue(this); return; }
if (act === "new") { doNew(); return; }
if (act === "load") { doLoad(); return; }
if (act === "options") { doOptions(); return; }
if (act === "galery") { doGallery (); return; }
if (act === "credits") { doCredits(); return; }
if (act === "quit") { doQuit(); return; }
if (wiki) {
if (wiki.indexOf("SupportMenu") !== -1) { doSupport(); return; }
if (wiki.indexOf("CreditsMenu") !== -1) { doCredits(); return; }
try { Wikifier.wikifyEval(String(wiki)); } catch (e) {}
return;
}
});
$(document)
.off("click.mm4MainConfirm")
.on("click.mm4MainConfirm", ".mm4-root .mm4-confirm [data-confirm]", function (ev) {
ev.preventDefault();
ev.stopPropagation();
var root = document.querySelector(".mm4-root");
if (!root) return;
var box = root.querySelector(".mm4-confirm");
if (!box) return;
var v = this.getAttribute("data-confirm");
if (v === "yes") {
var fn = box._onYes;
closeConfirm();
try { fn && fn(); } catch (e) {}
return;
}
closeConfirm();
});
$(document)
.off("click.mm4MainBackdrop")
.on("click.mm4MainBackdrop", ".mm4-root .mm4-confirm-backdrop", function () {
closeConfirm();
});
$(document)
.off("keydown.mm4Main")
.on("keydown.mm4Main", function (ev) {
var root = document.querySelector(".mm4-root");
if (!root) return;
var box = root.querySelector(".mm4-confirm");
if (box && box.classList.contains("is-open")) {
if (ev.key === "Escape" || ev.keyCode === 27) {
ev.preventDefault();
ev.stopPropagation();
closeConfirm();
}
return;
}
});
$(document).off("passagedisplay.mm4Upd").on(":passagedisplay.mm4Upd", function(){
updLoad();
setTimeout(function(){if(window.applyGlobalFontSize) window.applyGlobalFontSize();},50);
});
updLoad();
setTimeout(function(){if(window.applyGlobalFontSize) window.applyGlobalFontSize();},50);
})();<</script>><style>
html,body,#story,#passages,.passage{
margin:0 !important;
padding:0 !important;
min-width: 100% !important;
height:100% !important;
max-width:none !important;
background:#080808 !important;
overflow:hidden !important;
}
.mm4-root{height:100% !important;min-width: 100% !important;}
.mm4-bg{position:absolute !important;inset:0 !important;background:#080808 !important;background-image:url("assets/background.gif") !important;background-size:cover !important;background-position:center !important;background-repeat:no-repeat !important;opacity:.10 !important;pointer-events:none !important;transform:scale(1.02) !important;}
.mm4-ui{position:relative !important;z-index:2 !important;height:100vh !important;display:flex !important;flex-direction:row !important;box-sizing:border-box !important;}
.mm4-main{position:relative !important;z-index:2 !important;height:100% !important;display:flex !important;flex-direction:column !important;padding:clamp(20px,4vh,50px) 0 clamp(16px,3vh,40px) clamp(20px,5vw,80px) !important;box-sizing:border-box !important;flex:1 !important;}
.mm4-updates{margin:clamp(20px,3vh,50px) clamp(16px,3vw,70px) clamp(20px,3vh,50px) 0 !important;width:clamp(200px,20vw,320px) !important;max-width:clamp(200px,20vw,320px) !important;height:calc(100vh - clamp(40px,6vh,100px)) !important;padding:16px !important;box-sizing:border-box !important;display:flex !important;flex-direction:column !important;gap:8px !important;border-radius:5px !important;overflow:hidden !important;flex-shrink:0 !important;}
.mm4-upd-head{display:flex !important;align-items:center !important;align-self:center !important;flex:0 0 auto !important;}
.mm4-upd-title{font-weight:820 !important;letter-spacing:.8px !important;font-size:14px !important;color:rgba(255,255,255,.78) !important;text-transform:uppercase !important;}
.mm4-upd-body{display:flex !important;flex-direction:column !important;gap:10px !important;flex:1 1 auto !important;min-height:0 !important;overflow-y:auto !important;overflow-x:hidden !important;padding-right:4px !important;-webkit-overflow-scrolling:touch !important;}
.mm4-upd-item{border:1px solid rgba(255,255,255,.10) !important;background:rgba(255,255,255,.02) !important;border-radius:5px !important;padding:0 !important;box-sizing:border-box !important;overflow:hidden !important;display:block !important;backdrop-filter:blur(7px) !important;}
.mm4-upd-sum{list-style:none !important;cursor:pointer !important;display:flex !important;align-items:center !important;justify-content:space-between !important;gap:10px !important;padding:10px !important;}
.mm4-upd-sum::-webkit-details-marker{display:none !important;}
.mm4-upd-ver{font-weight:820 !important;letter-spacing:.3px !important;color:rgba(255,255,255,.92) !important;font-size:12px !important;display:inline-flex !important;align-items:center !important;gap:8px !important;}
.mm4-upd-news{display:inline-flex !important;align-items:center !important;justify-content:center !important;height:18px !important;padding:0 8px !important;border-radius:5px !important;border:1px solid rgba(255,90,90,.34) !important;background:rgba(255,90,90,.10) !important;color:rgba(255,230,230,.95) !important;font-size:10px !important;letter-spacing:.35px !important;font-weight:820 !important;}
.mm4-upd-datewrap{display:inline-flex !important;align-items:center !important;gap:6px !important;min-width:90px !important;justify-content:flex-end !important;}
.mm4-upd-date{font-size:11px !important;letter-spacing:.2px !important;color:rgba(255,255,255,.52) !important;}
.mm4-upd-arrow{display:inline-flex !important;align-items:center !important;justify-content:center !important;width:14px !important;height:14px !important;color:rgba(255,255,255,.52) !important;}
.mm4-upd-arrow::before{content:"◄" !important;}
.mm4-upd-item[open] .mm4-upd-arrow::before{content:"▼" !important;}
.mm4-upd-panel{
padding:0 10px 10px 10px !important;
max-height:clamp(80px,20vh,240px) !important;
overflow-y:auto !important;
overflow-x:hidden !important;
min-height:0 !important;
-webkit-overflow-scrolling:touch !important;
}
.mm4-upd-ttl{margin-top:2px !important;font-size:12px !important;line-height:1.35 !important;color:rgba(255,255,255,.86) !important;font-weight:760 !important;}
.mm4-upd-text{margin-top:6px !important;font-size:12px !important;line-height:1.35 !important;color:rgba(255,255,255,.74) !important;white-space:pre-wrap !important;}
.mm4-upd-foot{margin-top:auto !important;display:flex !important;align-items:center !important;justify-content:flex-start !important;}
.mm4-upd-hint{font-size:11px !important;letter-spacing:.2px !important;color:rgba(255,255,255,.45) !important;}
.mm4-header{
display:flex !important;
flex-direction:column !important;
margin:0 0 auto 0 !important;
}
.mm4-logo{
max-width:clamp(380px,45vw,700px) !important;
max-height:clamp(100px,28vh,280px) !important;
min-width:0 !important;
min-height:0 !important;
width:auto !important;
height:auto !important;
object-fit:contain !important;
object-position:left top !important;
margin-left: unset;
user-select:none !important;
-webkit-user-drag:none !important;
filter:drop-shadow(0 18px 44px rgba(0,0,0,.65)) !important;
}
.mm4-menu{
display:flex !important;
flex-direction:column !important;
gap:clamp(10px,2.5vh,30px) !important;
margin:0 !important;
padding:0 !important;
max-width:220px !important;
}
.mm4-item{position:relative !important;appearance:none !important;-webkit-appearance:none !important;border:0 !important;background:transparent !important;color:rgba(255,255,255,.78) !important;cursor:pointer !important;text-align:left !important;padding:0 !important;outline:none !important;}
.mm4-item::before{content:"" !important;position:absolute !important;left:-22px !important;top:8px !important;width:10px !important;height:10px !important;border-radius:999px !important;background:rgba(255,255,255,0) !important;box-shadow:0 0 0 rgba(255,255,255,0) !important;transition:background .14s ease, box-shadow .14s ease, transform .14s ease !important;}
.mm4-item::after{content:"" !important;position:absolute !important;left:0 !important;right:auto !important;bottom:-8px !important;width:0 !important;height:2px !important;background:rgba(255,255,255,.70) !important;box-shadow:0 0 22px rgba(255,255,255,.22) !important;transition:width .18s ease !important;}
.mm4-label{display:block !important;font-weight:820 !important;letter-spacing:.9px !important;font-size:calc(clamp(18px,2.2vh,26px) + var(--font-boost,0px)) !important;line-height:1.1 !important;text-transform:uppercase !important;text-shadow:0 2px 14px rgba(0,0,0,.7) !important;}
.mm4-desc{display:block !important;margin-top:clamp(2px,0.5vh,6px) !important;font-size:calc(clamp(13px,1.5vh,17px) + var(--font-boost,0px)) !important;letter-spacing:.2px !important;color:rgba(255,255,255,.56) !important;text-shadow:0 1px 12px rgba(0,0,0,.7) !important;}
.mm4-item:hover{color:rgba(255,255,255,.92) !important;}
.mm4-item:hover::before{background:rgba(255,255,255,.85) !important;box-shadow:0 0 22px rgba(255,255,255,.25) !important;transform:scale(1.05) !important;}
.mm4-item:hover::after{width:220px !important;}
.mm4-item:focus{color:rgba(255,255,255,.92) !important;}
.mm4-item:focus::before{background:rgba(255,255,255,.92) !important;box-shadow:0 0 26px rgba(255,255,255,.28) !important;}
.mm4-item:focus::after{width:260px !important;}
.mm4-continue .mm4-label{color:#f4f4f6 !important;}
.mm4-danger .mm4-label{color:rgba(255,190,190,.92) !important;}
.mm4-danger:hover .mm4-label{color:rgba(255,220,220,.98) !important;}
.mm4-item.is-busy{opacity:.7 !important;pointer-events:none !important;}
.mm4-bottom{margin-top:auto !important;display:flex !important;align-items:flex-end !important;justify-content:space-between !important;gap:18px !important;padding-bottom:clamp(16px,3vh,50px) !important;}
.mm4-leftnote{font-size:calc(clamp(13px,1.3vh,16px) + var(--font-boost,0px)) !important;letter-spacing:.22px !important;color:rgba(255,255,255,.55) !important;text-shadow:0 1px 12px rgba(0,0,0,.7) !important;}
.mm4-confirm{position:absolute !important;inset:0 !important;z-index:50 !important;display:none !important;}
.mm4-confirm.is-open{display:block !important;}
.mm4-confirm-backdrop{position:absolute !important;inset:0 !important;background:rgba(0,0,0,.62) !important;backdrop-filter:blur(2px) !important;-webkit-backdrop-filter:blur(2px) !important;}
.mm4-confirm-card{position:absolute !important;left:clamp(20px,6vw,86px) !important;top:50% !important;transform:translateY(-50%) !important;width:min(520px, calc(100vw - 120px)) !important;border:1px solid rgba(255,255,255,.14) !important;background:rgba(18,18,20,.92) !important;border-radius:12px !important;box-shadow:0 20px 60px rgba(0,0,0,.65) !important;padding:16px 16px 14px 16px !important;box-sizing:border-box !important;}
.mm4-confirm-title{font-weight:820 !important;letter-spacing:.4px !important;color:rgba(255,255,255,.92) !important;margin:0 0 8px 0 !important;text-transform:uppercase !important;}
.mm4-confirm-msg{color:rgba(255,255,255,.82) !important;line-height:1.35 !important;margin:0 0 14px 0 !important;}
.mm4-confirm-actions{display:flex !important;gap:10px !important;justify-content:flex-end !important;align-items:center !important;}
.mm4-cbtn{appearance:none !important;-webkit-appearance:none !important;border:1px solid rgba(255,255,255,.14) !important;background:rgba(18,18,20,.78) !important;color:#f4f4f6 !important;border-radius:10px !important;padding:10px 14px !important;font-weight:760 !important;letter-spacing:.2px !important;cursor:pointer !important;min-width:140px !important;}
.mm4-cbtn:hover{filter:brightness(1.08) !important;}
.mm4-cbtn-danger{border-color:rgba(255,90,90,.34) !important;background:rgba(35,16,16,.72) !important;}
@media (max-width:900px){
.mm4-updates{display:none !important;}
.mm4-main{padding:clamp(16px,3vh,40px) 0 clamp(12px,2vh,30px) clamp(16px,4vw,30px) !important;}
.mm4-confirm-card{left:22px !important;width:min(520px, calc(100vw - 44px)) !important;}
.mm4-item::before{left:-16px !important;}
.mm4-bottom{padding-right:18px !important;}
}
@media (max-width:520px){
.mm4-logo{max-width:min(380px,88vw) !important;max-height:clamp(70px,16vh,160px) !important;}
.mm4-menu{gap:clamp(6px,1.5vh,16px) !important;}
.mm4-label{font-size:clamp(11px,1.6vh,16px) !important;}
.mm4-item:hover::after{width:200px !important;}
.mm4-item:focus::after{width:220px !important;}
}
@media (max-height:500px){
.mm4-logo{max-height:clamp(40px,8vh,80px) !important;}
.mm4-menu{gap:clamp(4px,1vh,10px) !important;}
.mm4-desc{display:none !important;}
.mm4-label{font-size:clamp(10px,1.6vh,14px) !important;}
}
</style><<bgpause>><div id="achui-root"></div><<script>>
(function () {
var ACH_REWARDS_ENABLED = true;
function esc(s){return String(s==null?"":s).replace(/[&<>"']/g,function(c){return({"&":"&","<":"<",">":">",'"':""","'":"'"}[c]);});}
function getV(path){
try{
var V=State.variables;
if(!path) return undefined;
if(typeof path!=="string") return path;
if(path[0]==="$") path=path.slice(1);
var parts=path.split(".");
var v=V[parts[0]];
for(var i=1;i<parts.length;i++){
if(v==null) return undefined;
v=v[parts[i]];
}
return v;
}catch(e){return undefined;}
}
function boolV(path){return !!getV(path);}
function numV(path){
var v=getV(path);
var n=Number(v);
return Number.isFinite(n) ? n : 0;
}
function setV(path, val){
try{
if(!path) return;
if(typeof path!=="string") return;
if(path[0]==="$") path=path.slice(1);
State.variables[path]=val;
}catch(e){}
}
var RARITY_ORDER=["Secret","Legendary","Rare","Uncommon","Common"];
var RARITY_KEY={Secret:"secret",Legendary:"legendary",Rare:"rare",Uncommon:"uncommon",Common:"common"};
function getScrollTarget(){
var hb=document.getElementById("hubpass-body");
if(hb) return hb;
return document.scrollingElement || document.documentElement;
}
function forceScrollTop(){
try{
var st=getScrollTarget();
if(st) st.scrollTop=0;
window.scrollTo(0,0);
}catch(e){}
try{
var gl=document.querySelector("#achui-root .achGridWrap");
if(gl) gl.scrollTop=0;
}catch(e){}
}
function objDone(o){
var t=(o && o.type) ? o.type : "counter";
if(t==="flag") return boolV(o.finish);
var cur=numV(o.current);
var tar=Number(o.target);
if(!Number.isFinite(tar) || tar<=0) tar=1;
return cur>=tar;
}
function objProgress(o){
var t=(o && o.type) ? o.type : "counter";
if(t==="flag") return boolV(o.finish) ? 1 : 0;
var cur=numV(o.current);
var tar=Number(o.target);
if(!Number.isFinite(tar) || tar<=0) tar=1;
var r=cur/tar;
if(!Number.isFinite(r)) r=0;
if(r<0) r=0;
if(r>1) r=1;
return r;
}
function objLabel(o){
var t=(o && o.type) ? o.type : "counter";
if(t==="flag") return boolV(o.finish) ? "1 / 1" : "0 / 1";
var cur=numV(o.current);
var tar=Number(o.target);
if(!Number.isFinite(tar) || tar<=0) tar=1;
return String(cur)+" / "+String(tar);
}
function normalizeReward(r){
if(!r || typeof r!=="object") return null;
var out={
enabled: !!r.enabled,
type: String(r.type||"").trim(),
label: String(r.label||"").trim(),
amount: Number(r.amount||0),
varPath: (r.var!=null ? String(r.var) : null),
icon: (r.icon!=null ? String(r.icon) : null),
apply: (typeof r.apply==="function" ? r.apply : null)
};
if(!out.type) return null;
if(!Number.isFinite(out.amount)) out.amount=0;
return out;
}
function rewardKey(id){return "_AchRewarded_"+String(id||"");}
function rewardCollected(id){
return !!State.variables[rewardKey(id)];
}
function rewardAvailable(a){
if(!ACH_REWARDS_ENABLED) return false;
var r=normalizeReward(a && a.reward);
return !!(r && r.enabled);
}
function applyReward(reward){
if(!ACH_REWARDS_ENABLED) return false;
var r=normalizeReward(reward);
if(!r || !r.enabled) return false;
if(r.type==="varAdd"){
if(!r.varPath) return false;
var cur=numV(r.varPath);
setV(r.varPath, cur + r.amount);
return true;
}
if(r.type==="varSet"){
if(!r.varPath) return false;
setV(r.varPath, r.amount);
return true;
}
if(r.type==="flag"){
if(!r.varPath) return false;
setV(r.varPath, true);
return true;
}
if(r.type==="custom"){
if(r.apply){
try{ r.apply(State.variables); return true; }catch(e){ return false; }
}
return false;
}
return false;
}
function rewardLine(a){
if(!rewardAvailable(a)) return "";
var r=normalizeReward(a.reward);
var icon=r.icon!=null ? r.icon : "🎁";
var t=r.type;
var label=r.label || "Reward";
var amount=(t==="varAdd" || t==="varSet") ? r.amount : null;
var right = (amount!=null) ? ('<span class="achRewardVal">+'+esc(amount)+'</span>') : '';
return ''+
'<div class="achRewardLine">'+
'<div class="achRewardIcon">'+esc(icon)+'</div>'+
'<div class="achRewardText">'+esc(label)+'</div>'+
right+
'</div>';
}
function rewardSection(a, isDone){
if(!rewardAvailable(a)) return "";
var collected=rewardCollected(a.id);
var btn = "";
if(isDone){
if(collected){
btn = '<div class="achRewardBtn isDone" aria-disabled="true">REWARD COLLECTED</div>';
}else{
btn = '<div class="achRewardBtn" data-achreward="collect" data-achid="'+esc(a.id)+'">COLLECT REWARD</div>';
}
}
return ''+
'<div class="achRewardBox">'+
'<div class="achRewardTitle">REWARD</div>'+
rewardLine(a)+
btn+
'</div>';
}
function achStats(a){
var objs=(a && a.objectives) ? a.objectives : [];
var total=objs.length || 1;
var done=0;
var sum=0;
var anyProg=false;
for(var i=0;i<objs.length;i++){
var o=objs[i];
var d=objDone(o);
if(d) done++;
var p=objProgress(o);
sum+=p;
if(p>0 && p<1) anyProg=true;
if(p>=1) anyProg=true;
}
var isDone=(done===total) && objs.length>0;
var pct=objs.length ? Math.round((sum/total)*100) : (isDone?100:0);
if(isDone) pct=100;
var rarity=(a && a.rarity) ? a.rarity : "Common";
if(RARITY_ORDER.indexOf(rarity)===-1) rarity="Common";
var isSecret = (rarity==="Secret");
var gated = (a && a.unlock) ? (!boolV(a.unlock) && !isDone) : false;
var isLocked = gated || (!isDone && !!a.lockedByDefault);
var isInProgress = !isDone && !isLocked && (anyProg || pct>0);
return { total:total, done:done, pct:pct, isDone:isDone, isLocked:isLocked, isInProgress:isInProgress, rarity:rarity, isSecret:isSecret };
}
function aggregateStats(data){
var total=data.length;
var done=0;
var byRarityDone={Secret:0,Legendary:0,Rare:0,Uncommon:0,Common:0};
var byRarityTotal={Secret:0,Legendary:0,Rare:0,Uncommon:0,Common:0};
for(var i=0;i<data.length;i++){
var a=data[i];
var s=achStats(a);
byRarityTotal[s.rarity]=(byRarityTotal[s.rarity]||0)+1;
if(s.isDone){
done++;
byRarityDone[s.rarity]=(byRarityDone[s.rarity]||0)+1;
}
}
var pct= total ? Math.round((done/total)*100) : 0;
return { total:total, done:done, pct:pct, byRarityDone:byRarityDone, byRarityTotal:byRarityTotal };
}
function activeRaritySet(state){
var arr=Array.isArray(state.rarities) ? state.rarities.slice() : RARITY_ORDER.slice();
if(!arr.length) arr=RARITY_ORDER.slice();
var set={};
for(var i=0;i<arr.length;i++) set[arr[i]]=true;
return set;
}
function sortForView(list, mode){
return list.slice().sort(function(a,b){
var sa=achStats(a), sb=achStats(b);
var aUnclaimed = sa.isDone && rewardAvailable(a) && !rewardCollected(a.id);
var bUnclaimed = sb.isDone && rewardAvailable(b) && !rewardCollected(b.id);
if(aUnclaimed !== bUnclaimed) return aUnclaimed ? -1 : 1;
var aGroup=0, bGroup=0;
if(mode==="all"){
aGroup = sa.isInProgress ? 0 : (sa.isDone ? 2 : 1);
bGroup = sb.isInProgress ? 0 : (sb.isDone ? 2 : 1);
}else if(mode==="progress"){
aGroup = sa.isInProgress ? 0 : 1;
bGroup = sb.isInProgress ? 0 : 1;
}else if(mode==="done"){
aGroup = sa.isDone ? 0 : 1;
bGroup = sb.isDone ? 0 : 1;
}
if(aGroup!==bGroup) return aGroup-bGroup;
var ra=RARITY_ORDER.indexOf(sa.rarity);
var rb=RARITY_ORDER.indexOf(sb.rarity);
if(ra!==rb) return ra-rb;
if(sa.isDone!==sb.isDone) return sa.isDone ? 1 : -1;
if(sa.pct!==sb.pct) return sb.pct-sa.pct;
var ta=String(a.title||"").toLowerCase();
var tb=String(b.title||"").toLowerCase();
if(ta<tb) return -1;
if(ta>tb) return 1;
return 0;
});
}
function applyHubBodyNoScroll(){
var hb=document.getElementById("hubpass-body");
if(!hb) return null;
forceScrollTop();
hb.classList.add("hubpass-body-noscroll");
var mo=new MutationObserver(function(){
var stillThere=document.getElementById("achui-root");
if(!stillThere){
try{hb.classList.remove("hubpass-body-noscroll");}catch(e){}
try{mo.disconnect();}catch(e){}
try{hb.scrollTop=0;}catch(e){}
try{window.scrollTo(0,0);}catch(e){}
}
});
try{mo.observe(hb,{childList:true,subtree:true});}catch(e){}
return mo;
}
function render(root, data, state){
var mode=state.mode||"all";
var selectedId=state.selectedId||null;
var dropdownOpen=!!state.dropdownOpen;
var raritySet=activeRaritySet(state);
var agg=aggregateStats(data);
var filtered=data.filter(function(a){
var s=achStats(a);
if(mode==="progress" && !s.isInProgress) return false;
if(mode==="done" && !s.isDone) return false;
if(!raritySet[s.rarity]) return false;
return true;
});
var sorted=sortForView(filtered, mode);
var existsSelected = selectedId && sorted.some(function(a){return a.id===selectedId;});
if(!existsSelected) selectedId=null;
var tabs =
'<div class="achTabs">'+
'<div class="achTab'+(mode==="all"?' isActive':'')+'" data-achmode="all">ALL</div>'+
'<div class="achTab'+(mode==="progress"?' isActive':'')+'" data-achmode="progress">IN PROGRESS</div>'+
'<div class="achTab'+(mode==="done"?' isActive':'')+'" data-achmode="done">COMPLETED</div>'+
'</div>';
var drop =
'<div class="achDrop'+(dropdownOpen?' isOpen':'')+'">'+
'<div class="achDropBtn" data-achdrop="toggle">'+
'<span class="achDropBtnTxt">FILTER</span>'+
'<span class="achDropBtnIcon">▾</span>'+
'</div>'+
'<div class="achDropMenu">'+
RARITY_ORDER.map(function(r){
var on=!!raritySet[r];
var key=RARITY_KEY[r]||"common";
return ''+
'<div class="achDropRow '+esc(key)+'" data-achcheck="'+esc(r)+'">'+
'<div class="achDropBox'+(on?' isOn':'')+'"></div>'+
'<div class="achDropLbl">'+esc(r).toUpperCase()+'</div>'+
'</div>';
}).join("")+
'<div class="achDropLine"></div>'+
'<div class="achDropActions">'+
'<div class="achDropAct" data-achdrop="all">ALL</div>'+
'</div>'+
'</div>'+
'</div>';
var controlsRow =
'<div class="achControlsRow">'+
tabs+
drop+
'</div>';
var summary =
'<div class="achSummary">'+
'<div class="achSummaryLeft">'+
'<div class="achRing" aria-hidden="true">'+
'<div class="achRingInner">'+
'<div class="achRingPct">'+esc(agg.pct)+'%</div>'+
'</div>'+
'</div>'+
'</div>'+
'<div class="achSummaryRight">'+
'<div class="achSummaryTop">'+
'<div class="achSummaryLabel">UNLOCKED</div>'+
'<div class="achSummaryCount">'+
'<span class="achSummaryDone">'+esc(agg.done)+'</span>'+
'<span class="achSummarySep">/</span>'+
'<span class="achSummaryTotal">'+esc(agg.total)+'</span>'+
'</div>'+
'</div>'+
'<div class="achSummaryBreak">'+
'<div class="achBreakItem common"><span class="achBreakKey">COMMON</span><span class="achBreakVal">'+esc(agg.byRarityDone.Common)+'</span></div>'+
'<div class="achBreakItem uncommon"><span class="achBreakKey">UNCOMMON</span><span class="achBreakVal">'+esc(agg.byRarityDone.Uncommon)+'</span></div>'+
'<div class="achBreakItem rare"><span class="achBreakKey">RARE</span><span class="achBreakVal">'+esc(agg.byRarityDone.Rare)+'</span></div>'+
'<div class="achBreakItem legendary"><span class="achBreakKey">LEGENDARY</span><span class="achBreakVal">'+esc(agg.byRarityDone.Legendary)+'</span></div>'+
'<div class="achBreakItem secret"><span class="achBreakKey">SECRET</span><span class="achBreakVal">'+esc(agg.byRarityDone.Secret)+'</span></div>'+
'</div>'+
'</div>'+
'</div>';
var ringDeg = Math.max(0, Math.min(100, agg.pct)) * 3.6;
var cards = sorted.map(function(a){
var s=achStats(a);
var isSelected=(a.id===selectedId);
var rarityKey=RARITY_KEY[s.rarity]||"common";
var title = a.title||"";
var desc = a.desc||"";
var icon = a.icon||"★";
var progLabel = String(s.pct)+"%";
var ratio = "";
var objs=(a.objectives||[]);
if(objs.length===1){
ratio=objLabel(objs[0]);
}else if(objs.length>1){
ratio=String(s.done)+" / "+String(s.total);
}else{
ratio=s.isDone ? "1 / 1" : "0 / 1";
}
var hasReward = rewardAvailable(a);
var collected = hasReward ? rewardCollected(a.id) : false;
var rewardDotCls = "";
if(hasReward){
if(!s.isDone) rewardDotCls = " isPending";
else if(collected) rewardDotCls = " isCollected";
}
var rewardDot = hasReward ? ('<div class="achRewardDot'+rewardDotCls+'">🎁</div>') : '';
var details="";
if(isSelected){
if(s.isSecret && !s.isDone){
details =
'<div class="achExpand">'+
'<div class="achExpandTitle">HINT</div>'+
'<div class="achHintText">'+esc(a.hint||desc||"")+'</div>'+
'</div>';
}else{
details =
'<div class="achExpand">'+
'<div class="achExpandTitle">OBJECTIVES</div>'+
'<div class="achObjList">'+
objs.map(function(o){
var d=objDone(o);
var cls=d?" isDone":"";
var left=d?"✓":"•";
var label=objLabel(o);
var text=String(o.text||"");
return ''+
'<div class="achObj'+cls+'">'+
'<div class="achObjLeft">'+esc(left)+'</div>'+
'<div class="achObjMid">'+esc(text)+'</div>'+
'<div class="achObjRight">'+esc(label)+'</div>'+
'</div>';
}).join("")+
'</div>'+
'</div>';
}
var rw = rewardSection(a, s.isDone);
if(rw) details += rw;
}
var lockCls = "";
if(s.isLocked && !s.isSecret) lockCls=" isLocked";
if(s.isSecret && !s.isDone) lockCls+=" isSecretNoOpen";
var completedCls = (s.isDone && collected) ? " isCompleted" : "";
var selCls = isSelected ? " isSelected" : "";
return ''+
'<div class="achCard'+lockCls+completedCls+selCls+'" data-achid="'+esc(a.id)+'" data-rarity="'+esc(s.rarity)+'">'+
'<div class="achCardTop">'+
'<div class="achIcon">'+(String(icon).charAt(0)==='<' ? icon : esc(icon))+'</div>'+
'<div class="achTopMeta">'+
rewardDot+
'<div class="achRarity '+esc(rarityKey)+'">'+esc(s.rarity).toUpperCase()+'</div>'+
'</div>'+
'</div>'+
'<div class="achTitle">'+esc(title)+'</div>'+
'<div class="achDesc">'+esc(desc)+'</div>'+
'<div class="achProg">'+
'<div class="achProgLine">'+
'<div class="achProgRatio">'+esc(ratio)+'</div>'+
'<div class="achProgPct">'+esc(progLabel)+'</div>'+
'</div>'+
'<div class="achBar"><div class="achBarFill" style="width:'+esc(progLabel)+'"></div></div>'+
'</div>'+
details+
'</div>';
}).join("");
root.innerHTML =
'<div class="achUI">'+
'<div class="achHeader">'+
'<div class="achHeaderLeft">'+
'<div class="achH1">ACHIEVEMENTS</div>'+
'<div class="achH2">Track your progress. Unlocking achievements rewards you with unique content and reputation points.</div>'+
controlsRow+
'</div>'+
'<div class="achHeaderRight">'+summary+'</div>'+
'</div>'+
'<div class="achGridWrap">'+
(sorted.length ? '<div class="achGrid'+(selectedId?' hasOpen':'')+'">'+cards+'</div>' : '<div class="achEmpty">No achievements to display for this filter.</div>')+
'</div>'+
'</div>';
try{
var ring=root.querySelector(".achRing");
if(ring){
ring.style.setProperty("--deg", ringDeg+"deg");
}
}catch(e){}
forceScrollTop();
if(window.applyGlobalFontSize) window.applyGlobalFontSize();
}
function bind(root, data, state){
$(root).off("click.achui").on("click.achui", function(ev){
var t=ev.target;
var rewardBtn=t && t.closest ? t.closest("[data-achreward='collect']") : null;
if(rewardBtn){
var idr=rewardBtn.getAttribute("data-achid");
var ar=data.find(function(x){return x.id===idr;});
if(!ar) return;
var sr=achStats(ar);
if(!sr.isDone) return;
if(!rewardAvailable(ar)) return;
if(rewardCollected(ar.id)) return;
var ok=applyReward(ar.reward);
if(ok) State.variables[rewardKey(ar.id)]=true;
render(root, data, state);
return;
}
var tab=t && t.closest ? t.closest("[data-achmode]") : null;
if(tab){
state.mode=tab.getAttribute("data-achmode")||"all";
state.selectedId=null;
render(root, data, state);
return;
}
var dropBtn=t && t.closest ? t.closest("[data-achdrop]") : null;
if(dropBtn){
var act=dropBtn.getAttribute("data-achdrop");
if(act==="toggle"){
state.dropdownOpen=!state.dropdownOpen;
render(root, data, state);
return;
}
if(act==="all"){
state.rarities=RARITY_ORDER.slice();
state.selectedId=null;
render(root, data, state);
return;
}
if(act==="none"){
state.rarities=[];
state.selectedId=null;
render(root, data, state);
return;
}
}
var check=t && t.closest ? t.closest("[data-achcheck]") : null;
if(check){
var r=check.getAttribute("data-achcheck");
var arr=Array.isArray(state.rarities) ? state.rarities.slice() : RARITY_ORDER.slice();
var idx=arr.indexOf(r);
if(idx>=0) arr.splice(idx,1);
else arr.push(r);
arr=RARITY_ORDER.filter(function(x){return arr.indexOf(x)>=0;});
state.rarities=arr;
state.selectedId=null;
render(root, data, state);
return;
}
var clickInsideDrop = t && t.closest ? t.closest(".achDrop") : null;
if(!clickInsideDrop && state.dropdownOpen){
state.dropdownOpen=false;
render(root, data, state);
return;
}
var card=t && t.closest ? t.closest("[data-achid]") : null;
if(card){
var id=card.getAttribute("data-achid");
var a=data.find(function(x){return x.id===id;});
if(!a) return;
var s=achStats(a);
if(s.isLocked && !s.isSecret) return;
if(s.isSecret && !s.isDone) return;
state.selectedId = (state.selectedId===id) ? null : id;
render(root, data, state);
}
});
$(document).off(":.achuiScrollTop").on(":passagerender", function(){
forceScrollTop();
});
}
function initWhenReady(tries){
var root=document.getElementById("achui-root");
if(!root){
if(tries>0) requestAnimationFrame(function(){initWhenReady(tries-1);});
return;
}
if(root.dataset.achInit==="1") return;
root.dataset.achInit="1";
applyHubBodyNoScroll();
var data = Array.isArray(State.variables.Achievements)
? State.variables.Achievements
: setup.AchievementsData();
State.variables.Achievements = data;
var state=State.variables._AchUIState || { mode:"all", rarities:RARITY_ORDER.slice(), selectedId:null, dropdownOpen:false };
if(!Array.isArray(state.rarities)) state.rarities=RARITY_ORDER.slice();
State.variables._AchUIState=state;
render(root, data, state);
bind(root, data, state);
}
initWhenReady(120);
})();<</script>><style>
#achui-root{width:100%;height:100%;}
#hubpass-body.hubpass-body-noscroll{overflow:hidden !important;padding:0 !important;}
.achUI{height:100%;min-height:0;display:flex;flex-direction:column;gap:24px;padding:clamp(14px,3vw,26px);box-sizing:border-box;overflow:hidden;}
.achHeader{display:grid;grid-template-columns:1fr clamp(300px,50%,750px);gap:18px;align-items:start;flex:0 0 auto;}
.achHeaderLeft{min-width:0;}
.achH1{font-size:clamp(26px,4vw,46px);font-weight:950;letter-spacing:.02em;color:rgba(255,255,255,.95);line-height:1.02;}
.achH2{margin-top:8px;color:rgba(255,255,255,.55);font-size:calc(14px + var(--font-boost,0px));line-height:1.45;max-width:760px;}
.achControlsRow{margin-top:18px;display:flex;align-items:center;justify-content:space-between;gap:14px;flex-wrap:wrap;}
.achTabs{display:flex;gap:10px;flex-wrap:wrap;}
.achTab{padding:7px 14px;border-radius:8px;background:rgba(255,255,255,.05);border:1px solid rgba(255,255,255,.08);color:rgba(255,255,255,.70);font-weight:900;letter-spacing:.10em;font-size:calc(14px + var(--font-boost,0px));cursor:pointer;user-select:none;}
.achTab.isActive{background:rgba(230,87,99,.10);border-color:rgba(230,87,99,.35);color:rgba(230,87,99,.95);box-shadow:0 0 18px rgba(230,87,99,.10) inset;}
.achDrop{position:relative;flex:0 0 auto;}
.achDropBtn{display:flex;align-items:center;gap:10px;padding:7px 14px;border-radius:10px;background:rgba(255,255,255,.05);border:1px solid rgba(255,255,255,.10);color:rgba(255,255,255,.78);font-weight:950;letter-spacing:.10em;font-size:calc(14px + var(--font-boost,0px));cursor:pointer;user-select:none;}
.achDropBtnIcon{opacity:.75;}
.achDropMenu{position:absolute;right:0;top:44px;min-width:230px;border-radius:14px;background:rgba(12,12,12,.98);border:1px solid rgba(255,255,255,.12);box-shadow:0 22px 54px rgba(0,0,0,.65);padding:10px;display:none;z-index:50;}
.achDrop.isOpen .achDropMenu{display:block;}
.achDropRow{display:flex;align-items:center;gap:10px;padding:8px 10px;border-radius:10px;cursor:pointer;user-select:none;}
.achDropRow:hover{background:rgba(255,255,255,.05);}
.achDropBox{width:16px;height:16px;border-radius:4px;border:1px solid rgba(255,255,255,.18);background:rgba(255,255,255,.04);position:relative;flex:0 0 auto;}
.achDropBox.isOn{border-color:rgba(255,255,255,.30);background:rgba(255,255,255,.10);}
.achDropBox.isOn:after{content:"";position:absolute;left:4px;top:1px;width:6px;height:10px;border-right:2px solid rgba(255,255,255,.90);border-bottom:2px solid rgba(255,255,255,.90);transform:rotate(40deg);}
.achDropLbl{font-weight:950;letter-spacing:.12em;font-size:calc(14px + var(--font-boost,0px));}
.achDropRow.secret .achDropLbl{color:rgba(160,120,255,.95);}
.achDropRow.legendary .achDropLbl{color:rgba(230,87,99,.95);}
.achDropRow.rare .achDropLbl{color:rgba(160,200,255,.95);}
.achDropRow.uncommon .achDropLbl{color:rgba(140,255,200,.95);}
.achDropRow.common .achDropLbl{color:rgba(255,255,255,.80);}
.achDropLine{height:1px;background:rgba(255,255,255,.10);margin:8px 6px;}
.achDropActions{display:flex;gap:8px;padding:2px 6px 6px 6px;}
.achDropAct{flex:1 1 auto;text-align:center;padding:7px 10px;border-radius:10px;background:rgba(255,255,255,.05);border:1px solid rgba(255,255,255,.10);color:rgba(255,255,255,.78);font-weight:950;letter-spacing:.10em;font-size:calc(14px + var(--font-boost,0px));cursor:pointer;user-select:none;}
.achDropAct:hover{background:rgba(255,255,255,.08);}
.achHeaderRight{display:flex;justify-content:flex-end;}
.achSummary{width:100%;border-radius:14px;padding:14px 18px;background:rgba(15,15,15,.95);border:1px solid rgba(255,255,255,.10);position:relative;overflow:hidden;display:grid;grid-template-columns:86px 1fr;gap:14px;}
.achSummary:before{content:"";position:absolute;inset:0;pointer-events:none;}
.achSummaryLeft{display:flex;align-items:center;justify-content:center;position:relative;}
.achRing{width:72px;height:72px;border-radius:999px;display:flex;align-items:center;justify-content:center;background:conic-gradient(#e65763 var(--deg, 0deg), rgba(255,255,255,.12) 0deg);box-shadow:0 0 20px rgba(230,87,99,.10);}
.achRingInner{width:58px;height:58px;border-radius:999px;background:rgba(10,10,10,1);border:1px solid rgba(255,255,255,.10);display:flex;align-items:center;justify-content:center;}
.achRingPct{font-weight:950;color:rgba(255,255,255,.92);font-size:calc(14px + var(--font-boost,0px));letter-spacing:.02em;}
.achSummaryRight{position:relative;display:flex;flex-direction:column;gap:10px;min-width:0;}
.achSummaryTop{display:flex;align-items:baseline;justify-content:space-between;gap:12px;flex-wrap:wrap;}
.achSummaryLabel{color:rgba(255,255,255,.55);font-weight:900;letter-spacing:.14em;font-size:calc(14px + var(--font-boost,0px));}
.achSummaryCount{display:flex;align-items:baseline;gap:6px;}
.achSummaryDone{font-size:calc(16px + var(--font-boost,0px));font-weight:950;color:rgba(255,255,255,.95);line-height:1;}
.achSummarySep{font-size:calc(14px + var(--font-boost,0px));font-weight:900;color:rgba(255,255,255,.35);}
.achSummaryTotal{font-size:calc(14px + var(--font-boost,0px));font-weight:900;color:rgba(255,255,255,.55);}
.achSummaryBreak{display:grid;grid-template-columns:1fr 1fr;gap:6px 12px;}
.achBreakItem{display:flex;align-items:center;justify-content:space-between;gap:10px;min-width:0;}
.achBreakKey{font-weight:900;letter-spacing:.10em;font-size:calc(14px + var(--font-boost,0px));}
.achBreakVal{font-weight:950;font-size:calc(14px + var(--font-boost,0px));}
.achBreakItem.common .achBreakKey,.achBreakItem.common .achBreakVal{color:rgba(255,255,255,.80);}
.achBreakItem.uncommon .achBreakKey,.achBreakItem.uncommon .achBreakVal{color:rgba(140,255,200,.95);}
.achBreakItem.rare .achBreakKey,.achBreakItem.rare .achBreakVal{color:rgba(160,120,255,.95);}
.achBreakItem.legendary .achBreakKey,.achBreakItem.legendary .achBreakVal{color:rgba(230,87,99,.95);}
.achBreakItem.secret .achBreakKey,.achBreakItem.secret .achBreakVal{color:rgba(230,178,87,.95);}
.achGridWrap{flex:1 1 auto;min-height:0;overflow:auto;padding-right:4px;margin-top:10px;}
.achGrid{display:grid;grid-template-columns:repeat(4, minmax(200px, 1fr));gap:22px;padding:6px 2px 22px 2px;align-content:start;}
.achCard{position:relative;border-radius:14px;background:rgba(255,255,255,.04);border:1px solid rgba(255,255,255,.08);padding:clamp(10px,2vw,14px);overflow:hidden;cursor:pointer;user-select:none;transition:transform .16s ease, border-color .16s ease, background .16s ease, opacity .16s ease;}
.achCard:hover{transform:translateY(-2px);border-color:rgba(255,255,255,.16);background:rgba(255,255,255,.06);}
.achCard.isSelected{grid-column:1/-1;border-color:rgba(230,87,99,.50);z-index:20;}
.achCard.isLocked{opacity:.55;filter:blur(2.7px);pointer-events:none;}
.achCard.isSecretNoOpen{opacity:1;filter:none;}
.achCard.isCompleted{opacity:.50;}
.achCard.isCompleted .achRewardDot{opacity:.50;filter:grayscale(.3);}
.achCardTop{position:relative;display:flex;align-items:flex-start;justify-content:space-between;gap:12px;margin-bottom:10px;}
.achIcon{width:38px;height:38px;border-radius:10px;display:flex;align-items:center;justify-content:center;background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.10);color:rgba(255,255,255,.92);font-weight:950;font-size:calc(16px + var(--font-boost,0px));flex:0 0 auto;}
.achTopMeta{display:flex;align-items:center;justify-content:flex-end;gap:10px;flex:1 1 auto;flex-wrap:wrap;}
.achRewardDot{width:20px;height:20px;display:flex;align-items:center;justify-content:center;font-size:14px;line-height:1;transition:opacity .15s ease, filter .15s ease;}
.achRewardDot.isPending{opacity:.50;filter:grayscale(.6);}
.achRarity{padding:4px 10px;border-radius:999px;border:1px solid rgba(255,255,255,.10);font-weight:950;font-size:calc(14px + var(--font-boost,0px));letter-spacing:.12em;color:rgba(255,255,255,.88);background:rgba(255,255,255,.05);}
.achRarity.secret{background:rgba(190,148,87,.10);border-color:rgba(190,148,87,.30);color:rgba(230,178,87,.95);}
.achRarity.legendary{background:rgba(230,87,99,.10);border-color:rgba(230,87,99,.30);color:rgba(230,87,99,.95);}
.achRarity.rare{background:rgba(160,120,255,.10);border-color:rgba(160,120,255,.28);color:rgba(160,120,255,.95);}
.achRarity.uncommon{background:rgba(120,255,190,.08);border-color:rgba(120,255,190,.26);color:rgba(140,255,200,.95);}
.achRarity.common{background:rgba(255,255,255,.05);border-color:rgba(255,255,255,.12);color:rgba(255,255,255,.80);}
.achTitle{position:relative;color:rgba(255,255,255,.95);font-weight:950;font-size:calc(18px + var(--font-boost,0px));letter-spacing:.01em;line-height:1.15;}
.achDesc{position:relative;margin-top:8px;color:rgba(255,255,255,.55);font-size:calc(14px + var(--font-boost,0px));line-height:1.4;min-height:34px;}
.achProg{position:relative;margin-top:12px;display:flex;flex-direction:column;gap:8px;}
.achProgLine{display:flex;align-items:baseline;justify-content:space-between;gap:10px;}
.achProgRatio{color:rgba(255,255,255,.55);font-weight:900;font-size:calc(14px + var(--font-boost,0px));letter-spacing:.06em;}
.achProgPct{color:rgba(255,255,255,.78);font-weight:950;font-size:calc(14px + var(--font-boost,0px));}
.achBar{height:7px;border-radius:999px;background:rgba(255,255,255,.10);overflow:hidden;}
.achBarFill{height:100%;border-radius:999px;background:#e65763;box-shadow:0 0 16px rgba(230,87,99,.22);}
.achExpand{position:relative;margin-top:14px;border-top:1px solid rgba(255,255,255,.08);padding-top:12px;}
.achExpandTitle{color:rgba(255,255,255,.78);font-weight:950;font-size:calc(14px + var(--font-boost,0px));letter-spacing:.14em;text-transform:uppercase;margin-bottom:10px;}
.achObjList{display:flex;flex-direction:column;gap:8px;}
.achObj{display:grid;grid-template-columns:20px 1fr clamp(100px,20%,250px);gap:10px;align-items:center;border-radius:10px;padding:10px;background:rgba(0,0,0,.20);border:1px solid rgba(255,255,255,.08);}
.achObj.isDone{opacity:.65;background:rgba(255,255,255,.04);}
.achObjLeft{font-weight:950;color:rgba(255,255,255,.85);text-align:center;}
.achObjMid{color:rgba(255,255,255,.78);font-weight:400;font-size:calc(14px + var(--font-boost,0px));line-height:1.25;}
.achObjRight{color:rgba(255,255,255,.55);font-weight:950;font-size:calc(14px + var(--font-boost,0px));text-align:right;letter-spacing:.04em;}
.achHintText{color:rgba(255,255,255,.62);line-height:1.45;font-size:calc(14px + var(--font-boost,0px));}
.achRewardBox{margin-top:12px;border-radius:14px;border:1px solid rgba(255,255,255,.10);background:rgba(255,255,255,.04);padding:12px;}
.achRewardTitle{color:rgba(255,255,255,.78);font-weight:950;font-size:calc(14px + var(--font-boost,0px));letter-spacing:.14em;text-transform:uppercase;margin-bottom:10px;}
.achRewardLine{display:flex;align-items:center;justify-content:space-between;gap:10px;padding:10px;border-radius:12px;border:1px solid rgba(255,255,255,.10);background:rgba(0,0,0,.40);}
.achRewardIcon{width:28px;height:28px;border-radius:10px;display:flex;align-items:center;justify-content:center;background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.10);flex:0 0 auto;}
.achRewardText{color:rgba(255,255,255,.80);font-weight:600;font-size:calc(14px + var(--font-boost,0px));letter-spacing:.04em;flex:1 1 auto;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
.achRewardVal{color:rgba(255,255,255,.92);font-weight:600;font-size:calc(14px + var(--font-boost,0px));}
.achRewardBtn{margin-top:10px;padding:10px 12px;border-radius:12px;border:1px solid rgba(230,87,99,.30);background:rgba(230,87,99,.10);color:rgba(230,87,99,.95);font-weight:950;letter-spacing:.12em;font-size:calc(14px + var(--font-boost,0px));text-align:center;cursor:pointer;user-select:none;}
.achRewardBtn:hover{background:rgba(230,87,99,.14);}
.achRewardBtn.isDone{cursor:default;opacity:.55;border-color:rgba(255,255,255,.12);background:rgba(255,255,255,.05);color:rgba(255,255,255,.70);}
.achEmpty{padding:20px;color:rgba(255,255,255,.60);font-weight:800;background:rgba(255,255,255,.04);border:1px solid rgba(255,255,255,.08);border-radius:14px;}
@media (max-width:1400px){.achGrid{grid-template-columns:repeat(3, minmax(200px, 1fr));}}
@media (max-width:1100px){.achHeader{grid-template-columns:1fr;}.achHeaderRight{justify-content:flex-start;}.achGrid{grid-template-columns:repeat(2, minmax(200px, 1fr));}}
@media (max-width:720px){.achGrid{grid-template-columns:1fr;}.achHeader{grid-template-columns:1fr;}.achSummary{grid-template-columns:60px 1fr;}.achRing{width:52px;height:52px;}.achRingInner{width:40px;height:40px;}}
</style><<sound "music" "music.main" true>><div id="hubpass-root"></div><<script>>
(function(){
$(document).off(":passagedisplay.hubpass").on(":passagedisplay.hubpass",function(ev){
if(!ev||!ev.passage||ev.passage.title!=="HubMenu")return;
try{
setup.HubPass.isOpen=true;
setup.HubPass.render(String(State.variables.HubPassActiveKey||"OptionMenu"));
}catch(e){
try{console.error("HubMenu render failed:",e);}catch(e2){}
}
});
})();
<</script>><<bgpause>><div id="savemenu-root"></div>
<<script>>
(function () {
if (!window._smNames) window._smNames = {};
function esc(s) {
return String(s == null ? "" : s).replace(/[&<>"']/g, function(c) {
return {"&":"&","<":"<",">":">",'"':""","'":"'"}[c];
});
}
function pad2(n) { n = String(n|0); return n.length < 2 ? ("0"+n) : n; }
function fmtDate(ts) {
var d = ts ? new Date(ts) : null;
if (!d || isNaN(d.getTime())) return "";
return ["JAN","FEB","MAR","APR","MAY","JUN","JUL","AUG","SEP","OCT","NOV","DEC"][d.getMonth()] +
" " + pad2(d.getDate()) + ", " + d.getFullYear() +
" \u2022 " + pad2(d.getHours()) + ":" + pad2(d.getMinutes());
}
function buildSlotLine(i, save, isEmpty) {
var meta = save && save.metadata ? save.metadata : {};
var name = window._smNames[String(i)] || (meta.day != null ? "Day " + meta.day : (save ? (save.title || "Save") : "Empty Slot"));
var dateStr = save ? fmtDate(save.date) : "";
var badge = isEmpty ? "EMPTY" : ("SLOT " + pad2(i + 1));
return '<button class="slModalSlot" data-slotidx="' + i + '">' +
'<span class="slModalSlotBadge">' + badge + '</span>' +
'<span class="slModalSlotName">' + esc(name) + '</span>' +
(dateStr ? '<span class="slModalSlotDate">' + esc(dateStr) + '</span>' : '') +
'</button>';
}
window._smShowExportModal = function() {
var existing = document.getElementById("sl-export-modal");
if (existing) existing.remove();
var lines = "";
var hasSave = false;
for (var i = 0; i < 12; i++) {
if (window.SM.slotHas(i)) {
lines += buildSlotLine(i, window.SM.slotGet(i), false);
hasSave = true;
}
}
var modal = document.createElement("div");
modal.id = "sl-export-modal";
modal.className = "slModal";
modal.innerHTML =
'<div class="slModalBox">' +
'<div class="slModalTitle">Export Save</div>' +
'<div class="slModalSub">Choose which save to export as a file.</div>' +
'<div class="slModalSlotList">' +
(hasSave ? lines : '<div class="slModalEmpty">No saves found.</div>') +
'</div>' +
'<div class="slModalBtns">' +
'<button class="slModalBtn slModalBtnCancel" id="sl-export-cancel">Cancel</button>' +
'</div>' +
'</div>';
document.body.appendChild(modal);
document.getElementById("sl-export-cancel").onclick = function() { modal.remove(); };
modal.addEventListener("click", function(e) { if (e.target === modal) modal.remove(); });
modal.querySelectorAll(".slModalSlot").forEach(function(btn) {
btn.addEventListener("click", function() {
var idx = parseInt(this.getAttribute("data-slotidx"), 10);
modal.remove();
try {
var bundle = Save.base64.export();
var sv = window.SM.slotGet(idx);
var meta = sv && sv.metadata ? sv.metadata : {};
var name = window._smNames[String(idx)] || (meta.day != null ? "day-" + meta.day : "slot-" + (idx + 1));
var filename = "save-" + name.toLowerCase().replace(/\s+/g, "-") + "-" + new Date().toISOString().slice(0,10) + ".save";
var payload = JSON.stringify({ slot: idx, bundle: bundle });
var blob = new Blob([payload], { type: "application/json" });
var a = document.createElement("a");
a.href = URL.createObjectURL(blob);
a.download = filename;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(a.href);
} catch(err) {
console.error("[SM] Export failed:", err);
}
});
});
};
window._smPendingImport = null;
window._smShowImportModal = function() {
var existing = document.getElementById("sl-import-modal");
if (existing) existing.remove();
var lines = "";
for (var i = 0; i < 12; i++) {
lines += buildSlotLine(i, window.SM.slotGet(i), !window.SM.slotHas(i));
}
var modal = document.createElement("div");
modal.id = "sl-import-modal";
modal.className = "slModal";
modal.innerHTML =
'<div class="slModalBox">' +
'<div class="slModalTitle">Import Save</div>' +
'<div class="slModalSub">Choose the slot where this save will be imported.</div>' +
'<div class="slModalSlotList">' + lines + '</div>' +
'<div class="slModalBtns">' +
'<button class="slModalBtn slModalBtnCancel" id="sl-import-cancel">Cancel</button>' +
'</div>' +
'</div>';
document.body.appendChild(modal);
document.getElementById("sl-import-cancel").onclick = function() {
modal.remove();
window._smPendingImport = null;
};
modal.addEventListener("click", function(e) {
if (e.target === modal) { modal.remove(); window._smPendingImport = null; }
});
modal.querySelectorAll(".slModalSlot").forEach(function(btn) {
btn.addEventListener("click", function() {
var idx = parseInt(this.getAttribute("data-slotidx"), 10);
var occupied = window.SM.slotHas(idx);
modal.remove();
if (occupied) {
var confirmModal = document.createElement("div");
confirmModal.id = "sl-overwrite-modal";
confirmModal.className = "slModal";
var sv = window.SM.slotGet(idx);
var meta = sv && sv.metadata ? sv.metadata : {};
var saveName = window._smNames[String(idx)] || (meta.day != null ? "Day " + meta.day : "Slot " + (idx + 1));
confirmModal.innerHTML =
'<div class="slModalBox">' +
'<div class="slModalTitle">Overwrite Save?</div>' +
'<div class="slModalSub">Slot ' + pad2(idx + 1) + ' already contains <strong style="color:rgba(255,255,255,.75)">' + esc(saveName) + '</strong>. This cannot be undone.</div>' +
'<div class="slModalBtns">' +
'<button class="slModalBtn slModalBtnCancel" id="sl-overwrite-cancel">Cancel</button>' +
'<button class="slModalBtn slModalBtnConfirm" id="sl-overwrite-confirm">Overwrite</button>' +
'</div>' +
'</div>';
document.body.appendChild(confirmModal);
document.getElementById("sl-overwrite-cancel").onclick = function() {
confirmModal.remove();
window._smPendingImport = null;
};
confirmModal.addEventListener("click", function(e) {
if (e.target === confirmModal) { confirmModal.remove(); window._smPendingImport = null; }
});
document.getElementById("sl-overwrite-confirm").onclick = function() {
confirmModal.remove();
window._smDoImport(idx);
};
} else {
window._smDoImport(idx);
}
});
});
};
window._smDoImport = function(targetSlot) {
var pending = window._smPendingImport;
if (!pending) return;
window._smPendingImport = null;
var reader = new FileReader();
reader.onload = function(e) {
try {
var parsed = JSON.parse(e.target.result);
var bundle = parsed.bundle;
var srcSlot = parsed.slot;
Config.saves.id = "unveileddesire";
try {
var raw = LZString.decompressFromBase64(bundle);
if(raw) {
raw = raw.replace(/"id":"unveileddesire-public"/g, '"id":"unveileddesire"');
raw = raw.replace(/"id":"unveileddesire-premium"/g, '"id":"unveileddesire"');
bundle = LZString.compressToBase64(raw);
}
} catch(e) {}
Save.base64.import(bundle).then(function() {
if (srcSlot !== targetSlot) {
var data = localStorage.getItem("unveileddesire.save.slot.data:" + srcSlot);
var info = localStorage.getItem("unveileddesire.save.slot.info:" + srcSlot);
if (data) localStorage.setItem("unveileddesire.save.slot.data:" + targetSlot, data);
if (info) localStorage.setItem("unveileddesire.save.slot.info:" + targetSlot, info);
if (srcSlot !== targetSlot) {
localStorage.removeItem("unveileddesire.save.slot.data:" + srcSlot);
localStorage.removeItem("unveileddesire.save.slot.info:" + srcSlot);
}
}
if (typeof pending.onDone === "function") setTimeout(pending.onDone, 200);
}).catch(function(err) {
console.error("[SM] Import bundle failed:", err);
});
} catch(err) {
console.error("[SM] Import parse failed:", err);
}
};
reader.readAsText(pending.file);
};
function svgTrash() {
return '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><path fill="currentColor" d="M256 64C238.3 64 224 78.3 224 96L224 128L128 128C110.3 128 96 142.3 96 160C96 177.7 110.3 192 128 192L512 192C529.7 192 544 177.7 544 160C544 142.3 529.7 128 512 128L416 128L416 96C416 78.3 401.7 64 384 64L256 64zM160 256L160 512C160 547.3 188.7 576 224 576L416 576C451.3 576 480 547.3 480 512L480 256L160 256z"/></svg>';
}
function svgPlay() {
return '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><path fill="currentColor" d="M96 128C96 92.7 124.7 64 160 64C175.3 64 189.3 69.5 200 78.5L536 294.5C551.1 304.6 560 321.6 560 320C560 318.4 551.1 335.4 536 345.5L200 561.5C189.3 570.5 175.3 576 160 576C124.7 576 96 547.3 96 512L96 128z"/></svg>';
}
function svgPlus() {
return '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><path fill="currentColor" d="M288 128C288 110.3 302.3 96 320 96C337.7 96 352 110.3 352 128L352 288L512 288C529.7 288 544 302.3 544 320C544 337.7 529.7 352 512 352L352 352L352 512C352 529.7 337.7 544 320 544C302.3 544 288 529.7 288 512L288 352L128 352C110.3 352 96 337.7 96 320C96 302.3 110.3 288 128 288L288 288L288 128z"/></svg>';
}
function svgImport() {
return '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><path fill="rgb(230, 87, 99)" d="M352 96C352 78.3 337.7 64 320 64C302.3 64 288 78.3 288 96L288 306.7L246.6 265.3C234.1 252.8 213.8 252.8 201.3 265.3C188.8 277.8 188.8 298.1 201.3 310.6L297.3 406.6C309.8 419.1 330.1 419.1 342.6 406.6L438.6 310.6C451.1 298.1 451.1 277.8 438.6 265.3C426.1 252.8 405.8 252.8 393.3 265.3L352 306.7L352 96zM160 384C124.7 384 96 412.7 96 448L96 480C96 515.3 124.7 544 160 544L480 544C515.3 544 544 515.3 544 480L544 448C544 412.7 515.3 384 480 384L433.1 384L376.5 440.6C345.3 471.8 294.6 471.8 263.4 440.6L206.9 384L160 384zM464 440C477.3 440 488 450.7 488 464C488 477.3 477.3 488 464 488C450.7 488 440 477.3 440 464C440 450.7 450.7 440 464 440z"/></svg>';
}
function svgExport() {
return '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><path fill="rgb(230, 87, 99)" d="M352 173.3L352 384C352 401.7 337.7 416 320 416C302.3 416 288 401.7 288 384L288 173.3L246.6 214.7C234.1 227.2 213.8 227.2 201.3 214.7C188.8 202.2 188.8 181.9 201.3 169.4L297.3 73.4C309.8 60.9 330.1 60.9 342.6 73.4L438.6 169.4C451.1 181.9 451.1 202.2 438.6 214.7C426.1 227.2 405.8 227.2 393.3 214.7L352 173.3zM320 464C364.2 464 400 428.2 400 384L480 384C515.3 384 544 412.7 544 448L544 480C544 515.3 515.3 544 480 544L160 544C124.7 544 96 515.3 96 480L96 448C96 412.7 124.7 384 160 384L240 384C240 428.2 275.8 464 320 464zM464 488C477.3 488 488 477.3 488 464C488 450.7 477.3 440 464 440C450.7 440 440 450.7 440 464C440 477.3 450.7 488 464 488z"/></svg>';
}
function svgPencil() {
return '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><path fill="currentColor" d="M493.3 85.3C516.2 62.4 553.1 62.4 576 85.3C598.9 108.2 598.9 145.1 576 168L554.7 189.3L450.7 85.3L493.3 85.3zM424.5 111.6L528.4 215.5L240.9 503C231.6 512.3 219.8 518.6 207 521.1L117.6 539.1L135.6 449.7C138.1 436.9 144.4 425.1 153.7 415.8L424.5 111.6z"/></svg>';
}
function svgCalendar() {
return '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><path fill="rgb(230, 87, 99)" d="M224 64C206.3 64 192 78.3 192 96L192 128L160 128C124.7 128 96 156.7 96 192L96 240L544 240L544 192C544 156.7 515.3 128 480 128L448 128L448 96C448 78.3 433.7 64 416 64C398.3 64 384 78.3 384 96L384 128L256 128L256 96C256 78.3 241.7 64 224 64zM96 288L96 480C96 515.3 124.7 544 160 544L480 544C515.3 544 544 515.3 544 480L544 288L96 288z"/></svg>';
}
function svgScroll() {
return '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 640"><path fill="rgb(230, 87, 99)" d="M32 176C32 134.5 63.6 100.4 104 96.4L104 96L384 96C437 96 480 139 480 192L480 368L304 368C264.2 368 232 400.2 232 440L232 500C232 524.3 212.3 544 188 544C163.7 544 144 524.3 144 500L144 272L80 272C53.5 272 32 250.5 32 224L32 176zM268.8 544C275.9 530.9 280 515.9 280 500L280 440C280 426.7 290.7 416 304 416L552 416C565.3 416 576 426.7 576 440L576 464C576 508.2 540.2 544 496 544L268.8 544zM112 144C94.3 144 80 158.3 80 176L80 224L144 224L144 176C144 158.3 129.7 144 112 144z"/></svg>';
}
function buildCard(slotKey, save, labelText) {
var meta = save && save.metadata ? save.metadata : {};
var day = meta.day != null ? "Day " + meta.day : (save ? (save.title || "Save") : "");
var kStr = String(slotKey);
var displayName = window._smNames[kStr] || day;
var cheat = meta.cheatOn ? '<span class="slChip">CHEAT ON</span>' : '';
var k = esc(kStr);
var thumbImg = meta.thumbnail
? '<img src="' + esc(meta.thumbnail) + '" class="slThumbImg" alt="">'
: '';
var dateStr = fmtDate(save ? save.date : null);
var questLine = "";
if (meta.qDone != null && meta.qTotal != null && meta.qTotal > 0) {
var pct = Math.round((meta.qDone / meta.qTotal) * 100);
questLine =
'<span class="slMetaSep"></span>' +
'<span class="slMetaIco">' + svgScroll() + '</span>' +
'<span class="slMetaQuest">' + esc(pct) + '%</span>';
}
return (
'<div class="slCard" data-smslot="' + k + '">' +
'<div class="slThumb">' +
thumbImg +
'<div class="slBadge">' + esc(labelText) + '</div>' +
'</div>' +
'<div class="slMain">' +
'<div class="slTopRow">' +
'<div class="slTitle">' + esc(displayName) + '</div>' +
cheat +
'</div>' +
'<div class="slMeta">' +
(dateStr
? '<span class="slMetaIco slMetaIcoCal">' + svgCalendar() + '</span><span class="slMetaDate">' + esc(dateStr) + '</span>'
: '') +
questLine +
'</div>' +
'</div>' +
'<div class="slActions">' +
'<button class="slBtn slBtnRename" data-smact="rename" data-smslot="' + k + '" aria-label="Rename">' + svgPencil() + '</button>' +
'<button class="slBtn slBtnTrash" data-smact="delete" data-smslot="' + k + '" aria-label="Delete">' + svgTrash() + '</button>' +
'<button class="slBtn slBtnLoad" data-smact="load" data-smslot="' + k + '">' +
'<span class="slBtnIco">' + svgPlay() + '</span>' +
'<span class="slBtnTxt">Load</span>' +
'</button>' +
'</div>' +
'</div>'
);
}
function buildEmpty(nextNum) {
return (
'<div class="slCard slCreate" data-smempty="next">' +
'<div class="slThumb slThumbEmpty"><div class="slPlus">' + svgPlus() + '</div></div>' +
'<div class="slMain">' +
'<div class="slTopRow"><div class="slTitle">Create New Save</div></div>' +
'<div class="slMeta"><span class="slMetaDate">Empty Slot ' + pad2(nextNum) + '</span></div>' +
'</div>' +
'<div class="slActionsEmpty"></div>' +
'</div>'
);
}
function getMostRecent() {
var best = null, bestDate = 0;
if (window.SM.autoHas()) {
var a = window.SM.autoGet();
if (a && a.date && a.date > bestDate) { best = "auto"; bestDate = a.date; }
}
for (var i = 0; i < 12; i++) {
if (window.SM.slotHas(i)) {
var s = window.SM.slotGet(i);
if (s && s.date && s.date > bestDate) { best = i; bestDate = s.date; }
}
}
return best;
}
function getNextEmptySlot() {
for (var i = 0; i < 12; i++) {
if (!window.SM.slotHas(i)) return i;
}
return null;
}
function render(root) {
var html = "";
var filled = 0;
var inMainMenu = !!State.variables.InMainMenu;
if (window.SM.autoHas()) {
html += buildCard("auto", window.SM.autoGet(), "AUTO SAVE");
filled++;
}
for (var i = 0; i < 12; i++) {
if (window.SM.slotHas(i)) {
html += buildCard(i, window.SM.slotGet(i), "MANUAL " + pad2(i + 1));
filled++;
}
}
if (!inMainMenu) {
html += buildEmpty(filled + 1);
}
root.innerHTML =
'<div class="slWrap">' +
'<div class="slHead">' +
'<div class="slHeadTitle">Save <span class="slSlash">/</span> Load</div>' +
'<div class="slHeadSub">Select a slot to load your progress or manage save files.</div>' +
'</div>' +
'<div class="slPanel">' +
'<div class="slList">' + html + '</div>' +
'<div class="slFooter">' +
'<button class="slFootBtn" id="sm-import"><span class="slFootIco">' + svgImport() + '</span><span class="slFootTxt">Import Save</span></button>' +
(!inMainMenu ? '<button class="slFootBtn" id="sm-export"><span class="slFootIco">' + svgExport() + '</span><span class="slFootTxt">Export Save</span></button>' : '') +
'<button class="slResumeBtn" id="sm-resume"><span class="slResumeTxt">RESUME GAME</span><span class="slResumeArr">' + svgPlay() + '</span></button>' +
'<input type="file" id="sm-fileinput" accept=".save,.json" style="display:none;">' +
'</div>' +
'</div>' +
'</div>';
}
function doSave(root) {
var nextSlot = getNextEmptySlot();
if (nextSlot === null) return;
var V = State.variables;
var title = V.Day != null ? "Day " + V.Day : "Save";
window.SM.slotSave(nextSlot, title);
setTimeout(function() { render(root); bind(root); }, 300);
}
function doLoad(k) {
if (k === "auto") window.SM.autoLoad();
else window.SM.slotLoad(k);
setTimeout(function() {
if (window.setup && setup.HubPass) {
setup.HubPass.isOpen = false;
try { document.documentElement.classList.remove("hub-hidebars"); } catch(e) {}
State.variables.ShowTopUiBar = true;
State.variables.ShowBottomUiBar = true;
State.variables.HubPassReturnTo = null;
var r = document.getElementById("hubpass-root");
if (r) r.innerHTML = "";
}
try { Engine.show(); } catch(e) {}
}, 150);
}
function bind(root) {
$(root).off("click.sm").on("click.sm", function(ev) {
var t = ev.target;
var actEl = t.closest ? t.closest("[data-smact]") : null;
if (actEl) {
ev.stopPropagation();
var act = actEl.getAttribute("data-smact");
var raw = actEl.getAttribute("data-smslot");
var k = raw === "auto" ? "auto" : parseInt(raw, 10);
if (act === "rename") {
var existingModal = document.getElementById("sl-rename-modal");
if (existingModal) existingModal.remove();
var modal = document.createElement("div");
modal.id = "sl-rename-modal";
modal.innerHTML =
'<div class="slRenameBox">' +
'<div class="slRenameTitle">Rename Save</div>' +
'<input type="text" class="slRenameInput" id="sl-rename-inp" maxlength="30" placeholder="Enter save name...">' +
'<div class="slRenameHint">1 – 30 characters</div>' +
'<div class="slRenameBtns">' +
'<button class="slRenameBtn slRenameBtnCancel" id="sl-rename-cancel">Cancel</button>' +
'<button class="slRenameBtn slRenameBtnConfirm" id="sl-rename-confirm">Rename</button>' +
'</div>' +
'</div>';
modal.style.cssText = "position:fixed;inset:0;z-index:9999999;background:rgba(0,0,0,.75);display:flex;align-items:center;justify-content:center;backdrop-filter:blur(4px);";
document.body.appendChild(modal);
var inp = document.getElementById("sl-rename-inp");
var currentName = window._smNames[raw] || (function(){
var card = actEl.closest("[data-smslot]");
var titleEl = card ? card.querySelector(".slTitle") : null;
return titleEl ? titleEl.textContent.trim() : "";
})();
inp.value = currentName;
inp.focus();
inp.select();
function closeModal() {
var m = document.getElementById("sl-rename-modal");
if (m) m.remove();
}
function confirmRename() {
var newName = inp.value.trim();
if (newName.length < 1) return;
window._smNames[raw] = newName;
closeModal();
render(root);
bind(root);
}
document.getElementById("sl-rename-confirm").onclick = confirmRename;
document.getElementById("sl-rename-cancel").onclick = closeModal;
modal.addEventListener("click", function(e) { if (e.target === modal) closeModal(); });
inp.addEventListener("keydown", function(e) {
if (e.key === "Enter") { e.preventDefault(); confirmRename(); }
if (e.key === "Escape") { closeModal(); }
});
return;
}
if (act === "load") { doLoad(k); return; }
if (act === "delete") {
if (raw === "auto") window.SM.autoDelete();
else window.SM.slotDelete(k);
delete window._smNames[raw];
render(root);
bind(root);
return;
}
return;
}
var emptyEl = t.closest ? t.closest("[data-smempty]") : null;
if (emptyEl) {
if (!State.variables.InMainMenu) doSave(root);
return;
}
});
$("#sm-import").off("click.sm").on("click.sm", function() {
$("#sm-fileinput").trigger("click");
});
$("#sm-fileinput").off("change.sm").on("change.sm", function() {
var file = this.files && this.files[0];
if (!file) return;
window._smPendingImport = { file: file, onDone: function() { render(root); bind(root); } };
window._smShowImportModal();
this.value = "";
});
$("#sm-export").off("click.sm").on("click.sm", function() {
window.SM.exportSave();
});
$("#sm-resume").off("click.sm").on("click.sm", function() {
var recent = getMostRecent();
if (recent === null) {
if (window.setup && setup.HubPass) setup.HubPass.close();
return;
}
doLoad(recent);
});
}
function init(tries) {
var root = document.getElementById("savemenu-root");
if (!root) {
if (tries > 0) requestAnimationFrame(function() { init(tries - 1); });
return;
}
if (root.dataset.smInit === "1") return;
root.dataset.smInit = "1";
var hb = document.getElementById("hubpass-body");
if (hb) {
hb.classList.add("hubpass-body-noscroll");
hb.scrollTop = 0;
var mo = new MutationObserver(function() {
if (!document.getElementById("savemenu-root")) {
hb.classList.remove("hubpass-body-noscroll");
mo.disconnect();
}
});
mo.observe(hb, { childList: true, subtree: true });
}
render(root);
bind(root);
}
init(120);
})();
<</script>><style>
#savemenu-root { width:100%; height:100%; }
#savemenu-root * { box-sizing: border-box; }
#hubpass-body.hubpass-body-noscroll { overflow: hidden !important; padding: 0 !important; }
.slWrap { width:100%; height:100%; padding:clamp(16px,3vw,28px) clamp(16px,3vw,30px); overflow:hidden; display:flex; flex-direction:column; }
.slHead { padding: 6px 0 18px 0; flex: 0 0 auto; }
.slHeadTitle { font-size:clamp(26px,4vw,44px); font-weight:950; letter-spacing:.01em; color:rgba(255,255,255,.95); line-height:1.05; }
.slSlash { opacity:.40; font-weight:400; }
.slHeadSub { margin-top:8px; color:rgba(255,255,255,.38); font-size:calc(14px + var(--font-boost,0px)); line-height:1.55; }
.slPanel { flex:1 1 auto; min-height:0; display:flex; flex-direction:column; gap:18px; overflow:hidden; }
.slList { flex: 1 1 auto; min-height: 0; overflow-y: auto; padding: 2px 2px 8px 2px; display: flex; flex-direction: column; gap: 10px; scrollbar-width: thin; scrollbar-color: rgba(255,255,255,.08) transparent; }
.slList::-webkit-scrollbar { width: 6px; }
.slList::-webkit-scrollbar-thumb { background: rgba(255,255,255,.10); border-radius:999px; }
.slCard { position: relative; display: flex; align-items: center; gap: clamp(10px,2vw,18px); padding: clamp(10px,2vw,14px) clamp(12px,2vw,18px); border-radius: 10px; border: 1px solid rgba(255,255,255,.08); background: rgba(255,255,255,.02); cursor: pointer; user-select: none; min-height: 102px; overflow: hidden; transition: background 140ms, border-color 140ms; flex-wrap: wrap; }
.slCard::before { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 3px; background: #e65763; opacity: 0; transition: opacity 140ms; }
.slCard:hover { background: rgba(230,87,99,.04); border-color: rgba(255,255,255,.12); }
.slCard:hover::before { opacity: 1; }
.slCard:hover .slActions { opacity:1; transform:translateX(0); }
.slCreate { border-style: dashed; background: rgba(255,255,255,.01); }
.slCreate:hover { border-color: rgba(255,255,255,.16); background: rgba(255,255,255,.02); }
.slCreate::before { display: none; }
.slThumb { width: clamp(90px,12vw,154px); height: clamp(50px,7vw,80px); border-radius: 8px; border: 1px solid rgba(255,255,255,.10); background-color: rgba(0,0,0,.30); position: relative; overflow: hidden; flex: 0 0 auto; }
.slThumbImg { position: absolute !important; inset: 0 !important; width: 100% !important; height: 100% !important; min-width: 100% !important; max-width: 100% !important; min-height: 100% !important; max-height: 100% !important; object-fit: cover !important; display: block !important; z-index: 0 !important; }
.slBadge { position: absolute; left: 8px; top: 8px; z-index: 1; padding: 3px 8px; border-radius: 6px; font-size: calc(14px + var(--font-boost,0px)); font-weight: 950; letter-spacing: .10em; text-transform: uppercase; color: rgba(255,255,255,.90); background: rgba(0,0,0,.55); border: 1px solid rgba(255,255,255,.12); backdrop-filter: blur(4px); }
.slThumbEmpty { display:flex; align-items:center; justify-content:center; }
.slPlus { display:flex; align-items:center; justify-content:center; opacity:.45; }
.slPlus svg { width:22px; height:22px; }
.slMain { flex:1 1 auto; min-width:0; }
.slTopRow { display:flex; align-items:center; gap:10px; min-width:0; flex-wrap:wrap; }
.slTitle { font-size:calc(18px + var(--font-boost,0px)); font-weight:950; color:rgba(255,255,255,.92); white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.slChip { flex: 0 0 auto; padding: 2px 8px; border-radius: 6px; border: 1px solid rgba(230,87,99,.32); background: rgba(230,87,99,.10); color: #e65763; font-size: calc(14px + var(--font-boost,0px)); font-weight: 950; letter-spacing: .10em; text-transform: uppercase; }
.slMeta { margin-top:8px; display:flex; align-items:center; gap:6px; font-size:calc(14px + var(--font-boost,0px)); font-weight:500; letter-spacing:.04em; flex-wrap:wrap; }
.slMetaDate { color: rgba(255,255,255,.35); }
.slMetaSep { color: rgba(255,255,255,.15); width:1px; height:10px; background:rgba(255,255,255,.15); border-radius:999px; margin:0 4px; }
.slMetaIco { display:inline-flex; align-items:center; flex:0 0 auto; }
.slMetaIco svg { width:11px; height:11px; }
.slMetaIcoCal svg { color: rgba(255,255,255,.28); }
.slMetaQuest { color: rgba(255,255,255,.45); font-weight:700; }
.slRenameInput { font-size: calc(18px + var(--font-boost,0px)); font-weight: 950; color: rgba(255,255,255,.92); background: rgba(255,255,255,.06); border: 1px solid rgba(230,87,99,.50); border-radius: 6px; padding: 2px 8px; outline: none; width: 100%; max-width: 100%; caret-color: #e65763; }
.slActions { flex: 0 0 auto; display: flex; align-items: center; gap: 8px; opacity: 0; transform: translateX(12px); transition: opacity 140ms, transform 140ms; }
.slActionsEmpty { flex:0 0 auto; width:1px; }
.slBtn { all: unset; display: inline-flex; align-items: center; justify-content: center; height: 48px; border-radius: 10px; border: 1px solid rgba(255,255,255,.12); background: rgba(0,0,0,.35); cursor: pointer; user-select: none; transition: background 120ms, border-color 120ms; }
.slBtn:active { transform: translateY(1px); }
.slBtn svg { width: 20px; height: 20px; }
.slBtnRename { width: 48px; color: rgba(255,255,255,.45); border-color: rgba(255,255,255,.10); }
.slBtnRename:hover { background: rgba(255,255,255,.08); border-color: rgba(255,255,255,.22); color: rgba(255,255,255,.80); }
.slBtnTrash { width: 48px; color: rgba(230,87,99,.75); border-color: rgba(230,87,99,.18); }
.slBtnTrash:hover { background: rgba(230,87,99,.14); border-color: rgba(230,87,99,.35); color: #e65763; }
.slBtnLoad { gap: 10px; padding: 0 20px; color: rgba(255,255,255,.90); }
.slBtnLoad:hover { background: rgba(255,255,255,.09); border-color: rgba(255,255,255,.22); }
.slBtnIco { display:flex; align-items:center; }
.slBtnTxt { font-size:calc(14px + var(--font-boost,0px)); font-weight:950; letter-spacing:.10em; text-transform:uppercase; display: contents; }
.slFooter { flex: 0 0 auto; padding-top: 14px; border-top: 1px solid rgba(255,255,255,.07); display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.slFootBtn { all: unset; display: inline-flex; align-items: center; gap: 9px; height: 44px; padding: 0 16px; border-radius: 8px; border: 1px solid rgba(255,255,255,.10); background: rgba(255,255,255,.03); cursor: pointer; user-select: none; transition: background 120ms; }
.slFootBtn:hover { background: rgba(255,255,255,.07); }
.slFootBtn:active { transform: translateY(1px); }
.slFootIco { display:flex; align-items:center; }
.slFootIco svg { width:15px; height:15px; }
.slFootTxt { font-size:calc(14px + var(--font-boost,0px)); font-weight:950; letter-spacing:.08em; color:rgba(255,255,255,.70); }
.slResumeBtn { all: unset; margin-left: auto; height: 44px; min-width: clamp(180px,25vw,340px); padding: 0 20px; border-radius: 8px; border: 1px solid rgba(255,255,255,.12); background: rgba(255,255,255,.93); cursor: pointer; user-select: none; display: flex; align-items: center; justify-content: center; gap: 12px; transition: background 120ms; }
.slResumeBtn:hover { background: #fff; }
.slResumeBtn:active { transform: translateY(1px); }
.slResumeTxt { font-size:calc(14px + var(--font-boost,0px)); font-weight:950; letter-spacing:.12em; color:rgba(0,0,0,.90); display: contents; }
.slResumeArr { display:flex; align-items:center; }
.slResumeArr svg { width:14px; height:14px; }
.slResumeArr svg path { fill: rgba(0,0,0,.88) !important; }
.slRenameBox { background: rgba(12,12,12,1); border: 1px solid rgba(255,255,255,.10); border-radius: 14px; padding: clamp(16px,4vw,28px) clamp(18px,4vw,32px); width: min(420px,90vw); display: flex; flex-direction: column; gap: 14px; }
.slRenameTitle { font-size: calc(20px + var(--font-boost,0px)); font-weight: 950; color: rgba(255,255,255,.92); letter-spacing: .02em; }
.slRenameHint { font-size: calc(14px + var(--font-boost,0px)); color: rgba(255,255,255,.28); letter-spacing: .06em; margin-top: -6px; }
.slRenameBtns { display: flex; gap: 10px; justify-content: flex-end; margin-top: 4px; flex-wrap: wrap; }
.slRenameBtn { all: unset; padding: 9px 22px; border-radius: 8px; font-size: calc(14px + var(--font-boost,0px)); font-weight: 900; letter-spacing: .10em; text-transform: uppercase; cursor: pointer; border: 1px solid; transition: background 120ms; }
.slRenameBtnCancel { background: transparent; border-color: rgba(255,255,255,.12); color: rgba(255,255,255,.55); }
.slRenameBtnCancel:hover { background: rgba(255,255,255,.06); }
.slRenameBtnConfirm { background: #e65763; border-color: transparent; color: #fff; }
.slRenameBtnConfirm:hover { background: #d94d5a; }
.slModal { position: fixed; inset: 0; z-index: 9999999; background: rgba(0,0,0,.75); display: flex; align-items: center; justify-content: center; backdrop-filter: blur(4px); }
.slModalBox { background: rgba(12,12,12,1); border: 1px solid rgba(255,255,255,.10); border-radius: 14px; padding: clamp(16px,4vw,28px) clamp(18px,4vw,32px); width: min(460px,90vw); display: flex; flex-direction: column; gap: 14px; }
.slModalTitle { font-size: calc(20px + var(--font-boost,0px)); font-weight: 950; color: rgba(255,255,255,.92); letter-spacing: .02em; }
.slModalSub { font-size: calc(14px + var(--font-boost,0px)); color: rgba(255,255,255,.38); margin-top: -6px; }
.slModalSlotList { display: flex; flex-direction: column; gap: 8px; max-height: 280px; overflow-y: auto; scrollbar-width: thin; scrollbar-color: rgba(255,255,255,.08) transparent; }
.slModalSlot { all: unset; display: flex; align-items: center; gap: 14px; padding: 10px 14px; border-radius: 8px; border: 1px solid rgba(255,255,255,.08); background: rgba(255,255,255,.02); cursor: pointer; transition: background 120ms, border-color 120ms; }
.slModalSlot:hover { background: rgba(230,87,99,.06); border-color: rgba(230,87,99,.25); }
.slModalSlotBadge { font-size: calc(14px + var(--font-boost,0px)); font-weight: 950; letter-spacing: .10em; text-transform: uppercase; color: rgba(255,255,255,.5); background: rgba(255,255,255,.06); border: 1px solid rgba(255,255,255,.10); border-radius: 4px; padding: 3px 7px; flex: 0 0 auto; }
.slModalSlotName { font-size: calc(14px + var(--font-boost,0px)); font-weight: 700; color: rgba(255,255,255,.88); flex: 1; }
.slModalSlotDate { font-size: calc(14px + var(--font-boost,0px)); color: rgba(255,255,255,.30); }
.slModalEmpty { font-size: calc(14px + var(--font-boost,0px)); color: rgba(255,255,255,.35); text-align: center; padding: 18px 0; }
.slModalBtns { display: flex; gap: 10px; justify-content: flex-end; margin-top: 4px; flex-wrap: wrap; }
.slModalBtn { all: unset; padding: 9px 22px; border-radius: 8px; font-size: calc(14px + var(--font-boost,0px)); font-weight: 900; letter-spacing: .10em; text-transform: uppercase; cursor: pointer; border: 1px solid; transition: background 120ms; }
.slModalBtnCancel { background: transparent; border-color: rgba(255,255,255,.12); color: rgba(255,255,255,.55); }
.slModalBtnCancel:hover { background: rgba(255,255,255,.06); }
.slModalBtnConfirm { background: #e65763; border-color: transparent; color: #fff; }
.slModalBtnConfirm:hover { background: #d94d5a; }
</style><<sound "music" "music.music" true>><<passagebg>><img src="assets/img/misc/MCPC/internet/email/gmail.gif"/><</passagebg>>
<<InformationUiPopUp "Email">>
<<script>>
var V = State.variables;
var T = State.temporary;
T.mails = [];
if (!V.MailRead) V.MailRead = {};
for (var _i = 0; _i < setup.MailList.length; _i++) {
var _m = setup.MailList[_i];
var _flag = (V[_m.id] !== undefined ? V[_m.id] : null);
if (!V.MailRead[_m.id] && (_flag === true || (_m.id === "StartStoryMail" && (V.StartStoryMail === false || V.StartStoryMail === null)))) {
T.mails.push(_m);
}
}
V.MailInBox = (T.mails.length > 0);
<</script>><div class="ml-wrap"><<if $MailInBox>><div class="ml-header"><span class="ml-title">Inbox</span><span class="ml-count"><<print _mails.length>> 📧</span></div><ul class="ml-list"><<for _i = 0; _i < _mails.length; _i++>><<set _m = _mails[_i]>><<capture _m>><li class="ml-item"><<link _m.title>><<set $MailRead[_m.id] = true>><<set $MailReturnTo = passage()>><<set $MailInBox = setup.MailList.some(function(mm){return !$MailRead[mm.id]&&((State.variables[mm.id]!==undefined&&State.variables[mm.id]===true)||(mm.id=="StartStoryMail"&&(State.variables.StartStoryMail===false||State.variables.StartStoryMail==null)));})>><<goto _m.pass>><</link>></li><</capture>><</for>></ul><<else>><div class="ml-empty">No messages.</div><</if>></div>
<style>
.ml-wrap{width:100%;font-family:inherit;}
.ml-header{display:flex;align-items:center;justify-content:space-between;padding:0 0 10px 0;margin-bottom:6px;border-bottom:1px solid rgba(255,255,255,.07);}
.ml-title{font-size:18px;font-weight:950;color:rgba(255,255,255,.95);letter-spacing:-.01em;}
.ml-count {
font-size: 14px;
font-weight: 800;
color: rgba(255, 255, 255, 0.75);
letter-spacing: .08em;
}
.ml-list{list-style:none!important;padding:0!important;margin:0!important;}
.ml-item{margin:0!important;border-bottom:1px solid rgba(255,255,255,.05);}
.ml-item .link-internal{all:unset;display:flex!important;align-items:center;gap:10px;padding:10px 4px;cursor:pointer;width:100%;box-sizing:border-box;transition:background .10s;}
.ml-item .link-internal:hover{background:rgba(255,255,255,.04)!important;}
.ml-item .link-internal:active{background:rgba(255,255,255,.07)!important;}
.ml-item .link-internal::before {
content: "\1F4E7";
flex-shrink: 0;
width: 34px;
height: 34px;
border-radius: 999px;
display: flex;
align-items: center;
justify-content: center;
font-size: 16px;
box-sizing: border-box;
}
.ml-empty{padding:30px 0;text-align:center;color:rgba(255,255,255,.28);font-size:11px;font-weight:700;letter-spacing:.06em;}
</style>
<</InformationUiPopUp>>
<div class="BottomUiBarCustom">
<<BottomButton "Move">><<return [[↩️ Close Email|Internet]]>><</BottomButton>>
</div><<set $ShowTopUiBar = false>><<set $ShowBottomUiBar = false>>
<<if !$MindTargetNPC or $MindTargetNPC.id is undefined>><<goto "MindResult">><</if>><<set $MindNPCKey = "NPC" + String($MindTargetNPC.id)>><<set $MindNPCDisplay = $MindTargetNPC.name ? $MindTargetNPC.name : String($MindTargetNPC.id)>><style>
#passages{padding:0!important}
.passage{padding:0!important;max-width:none!important}
.BottomUiBarCustom,#ui-bar,.topUiBar{display:none!important}
#mg-outer{position:fixed;z-index:5;background:#06060c;overflow:hidden}
#mg-canvas{position:absolute;inset:0;width:100%;height:100%;display:block;cursor:crosshair}
#mg-hud{position:absolute;top:0;left:0;right:0;z-index:20;background:rgba(0,0,0,.88);backdrop-filter:blur(10px);border-bottom:1px solid rgba(255,255,255,.06);padding:10px 18px;display:flex;align-items:center;gap:12px}
#mg-score{color:#fff;font-size:1.05rem;font-weight:900;font-family:monospace;min-width:60px;transition:color .15s}
#mg-score.pop{animation:mgpop .13s ease}
@keyframes mgpop{0%{transform:scale(1)}50%{transform:scale(1.45)}100%{transform:scale(1)}}
#mg-combo{font-size:.72rem;font-weight:900;font-family:monospace;color:#fbbf24;opacity:0;transition:opacity .2s,color .2s;min-width:90px}
#mg-combo.show{opacity:1}
#mg-npcname{font-size:.62rem;text-transform:uppercase;letter-spacing:.14em;font-weight:700;white-space:nowrap;transition:color .3s,text-shadow .3s}
#mg-hint{position:absolute;bottom:22px;left:50%;transform:translateX(-50%);color:rgba(255,255,255,.25);font-size:.62rem;letter-spacing:.13em;font-family:monospace;pointer-events:none;transition:opacity .6s;white-space:nowrap;z-index:21;opacity:0}
#mg-timerbar-wrap{position:absolute;bottom:0;left:0;right:0;z-index:22;height:5px;background:rgba(255,255,255,.06)}
#mg-timerbar{height:100%;width:100%;transform-origin:left;transition:background .4s}
</style>
<div id="mg-outer"><canvas id="mg-canvas"></canvas>
<div id="mg-hud"><span id="mg-score">0 pts</span><span id="mg-combo"></span><span style="flex:1"></span><span id="mg-npcname">...</span></div>
<div id="mg-hint">CLICK WHEN THE RING ALIGNS WITH THE TARGET</div>
<div id="mg-timerbar-wrap"><div id="mg-timerbar"></div></div>
</div>
<<script>>
$(document).one(':passageend',function(){(function(){
var story=document.getElementById('story');
var sr=story?story.getBoundingClientRect():{top:0,left:0,width:window.innerWidth,height:window.innerHeight};
var outer=document.getElementById('mg-outer');
outer.style.top=sr.top+'px';outer.style.left=sr.left+'px';
outer.style.width=sr.width+'px';outer.style.height=sr.height+'px';
var canvas=document.getElementById('mg-canvas');
if(!canvas)return;
canvas.width=Math.round(sr.width);canvas.height=Math.round(sr.height);
var ctx=canvas.getContext('2d');
var W=canvas.width,H=canvas.height,HUD=44;
var V=State.variables;
var npc=V[V.MindNPCKey]||{mind:50,aff:0,cor:0,name:'???'};
var mind=Math.max(0,Math.min(250,Number(npc.mind)||0));
var aff=Math.max(0,Math.min(500,Number(npc.aff)||0));
var pp=Math.max(0,Number(V.PsychicPower)||0);
var mindNorm=mind/250,affNorm=aff/500;
var npcColor=(npc.color&&/^#[0-9a-fA-F]{3,8}$/.test(npc.color))?npc.color:'#a78bfa';
var nameEl=document.getElementById('mg-npcname');
if(nameEl){nameEl.textContent=npc.name||V.MindNPCDisplay||'???';nameEl.style.color=npcColor;}
var TR=Math.min(W,H)*0.11,startR=TR*4.0,MARGIN=TR*1.5;
var affTimeBonus=Math.min(15,Math.floor(aff/10)*0.5);
var affPenReduction=Math.floor(aff/100);
var MAX_TIME=10+affTimeBonus,timeLeft=MAX_TIME;
var goodHalf=TR*(0.14-mindNorm*0.07+affNorm*0.05),MIN_GOOD=TR*0.03;
function perfHalf(){return Math.max(TR*0.018,goodHalf*0.28);}
function missPenalty(){return Math.max(0,Math.round(1+mindNorm*2)-affPenReduction);}
// ═══════════════════════════════════════════════════
// AUDIO
// ═══════════════════════════════════════════════════
var audioCtx,musicBus,sfxBus,mRunning=false,mStep=0,mNextTime=0;
var approachOsc=null,approachGain=null;
function getMixVol(bus){try{var m=window.setup&&setup.AudioMixer?setup.AudioMixer:null;if(m&&typeof m._mixVol==='function')return Math.max(0,Math.min(1,m._mixVol(bus)));}catch(e){}return 1;}
function updateBusGains(){if(!audioCtx)return;if(musicBus)musicBus.gain.setTargetAtTime(getMixVol('music'),audioCtx.currentTime,0.05);if(sfxBus)sfxBus.gain.setTargetAtTime(getMixVol('sfx'),audioCtx.currentTime,0.05);}
function ensureAudio(){if(audioCtx)return;try{audioCtx=new(window.AudioContext||window.webkitAudioContext)();musicBus=audioCtx.createGain();musicBus.gain.value=getMixVol('music');musicBus.connect(audioCtx.destination);sfxBus=audioCtx.createGain();sfxBus.gain.value=getMixVol('sfx');sfxBus.connect(audioCtx.destination);}catch(e){}}
function makeOsc(type,freq,vol,dur,dest,t){if(!audioCtx)return;t=t||audioCtx.currentTime;var o=audioCtx.createOscillator(),g=audioCtx.createGain();o.type=type;o.frequency.value=freq;g.gain.setValueAtTime(0,t);g.gain.linearRampToValueAtTime(vol,t+0.004);g.gain.exponentialRampToValueAtTime(0.0001,t+dur);g.gain.linearRampToValueAtTime(0,t+dur+0.004);o.connect(g);g.connect(dest||sfxBus);o.start(t);o.stop(t+dur+0.006);}
function makeNoise(lowpass,vol,dur,dest,t){if(!audioCtx)return;t=t||audioCtx.currentTime;var sz=Math.floor(audioCtx.sampleRate*dur),buf=audioCtx.createBuffer(1,sz,audioCtx.sampleRate),d=buf.getChannelData(0);for(var i=0;i<sz;i++)d[i]=Math.random()*2-1;var src=audioCtx.createBufferSource(),f=audioCtx.createBiquadFilter(),g=audioCtx.createGain();f.type='lowpass';f.frequency.value=lowpass;src.buffer=buf;g.gain.setValueAtTime(0,t);g.gain.linearRampToValueAtTime(vol,t+0.004);g.gain.exponentialRampToValueAtTime(0.0001,t+dur);g.gain.linearRampToValueAtTime(0,t+dur+0.004);src.connect(f);f.connect(g);g.connect(dest||sfxBus);src.start(t);src.stop(t+dur+0.006);}
// ═══════════════════════════════════════════════════
// MUSIC ENGINE
// ═══════════════════════════════════════════════════
var BPM=150,MSTEP=60/BPM/4,MBAR=16;
var Mpseq=[0,1,0,2,0,1,0,3];
var MKICK=[[1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0],[1,0,0,0,1,0,1,0,1,0,0,0,1,0,0,0],[1,1,0,0,1,0,0,0,1,0,0,0,1,0,1,0],[1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,1]];
var MSNARE=[[0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0],[0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0],[0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0],[0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0]];
var MHIHAT=[[1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0],[1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0],[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1],[1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0]];
var MOPEN=[[0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1],[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],[0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0]];
var MBASS=[[110,0,110,0,131,0,131,0,110,0,165,0,147,131,110,0],[110,0,131,0,147,0,165,0,131,0,110,0,98,110,0,0],[110,110,0,0,110,0,110,0,131,0,131,0,147,165,147,0],[98,0,0,0,110,0,0,0,131,0,0,0,165,0,147,0]];
var MLEAD=[[0,0,659,0,0,0,880,0,784,0,0,659,587,0,523,0],[880,0,0,784,659,0,0,587,0,0,659,0,784,880,784,659],[0,659,784,0,880,0,784,659,587,0,659,784,880,0,0,880],[784,0,880,0,0,784,659,0,587,659,0,0,440,523,659,0]];
var mDyn={tempo:1,leadVol:0.04,bassVol:0.18,kickVol:0.7,hihatVol:0.03};
function updateMDyn(combo,tl,mt,miss){var ci=Math.min(1,combo/8),urg=Math.max(0,1-tl/mt),mf=miss>1?0.88:1;var targetTempo=1+ci*0.08+urg*0.06;mDyn.tempo+=(targetTempo-mDyn.tempo)*0.02;mDyn.leadVol=(0.035+ci*0.04+urg*0.025)*mf;mDyn.bassVol=(0.16+ci*0.06+urg*0.04)*mf;mDyn.kickVol=(0.6+ci*0.15+urg*0.12)*mf;mDyn.hihatVol=(0.022+ci*0.022+urg*0.018)*mf;if(musicBus)musicBus.gain.setTargetAtTime(getMixVol('music'),audioCtx.currentTime,0.08);}
function sKick(t){var o=audioCtx.createOscillator(),g=audioCtx.createGain();o.type='sine';o.frequency.setValueAtTime(160,t);o.frequency.exponentialRampToValueAtTime(42,t+0.09);g.gain.setValueAtTime(0,t);g.gain.linearRampToValueAtTime(mDyn.kickVol,t+0.004);g.gain.exponentialRampToValueAtTime(0.0001,t+0.28);g.gain.linearRampToValueAtTime(0,t+0.285);o.connect(g);g.connect(musicBus);o.start(t);o.stop(t+0.29);}
function sSnare(t){var nb=Math.floor(audioCtx.sampleRate*0.11),buf=audioCtx.createBuffer(1,nb,audioCtx.sampleRate),d=buf.getChannelData(0);for(var i=0;i<nb;i++)d[i]=Math.random()*2-1;var src=audioCtx.createBufferSource(),f=audioCtx.createBiquadFilter(),g=audioCtx.createGain();f.type='bandpass';f.frequency.value=1600;f.Q.value=0.7;src.buffer=buf;g.gain.setValueAtTime(0,t);g.gain.linearRampToValueAtTime(0.26,t+0.004);g.gain.exponentialRampToValueAtTime(0.0001,t+0.09);g.gain.linearRampToValueAtTime(0,t+0.095);src.connect(f);f.connect(g);g.connect(musicBus);src.start(t);src.stop(t+0.1);var o=audioCtx.createOscillator(),og=audioCtx.createGain();o.type='triangle';o.frequency.value=170;og.gain.setValueAtTime(0,t);og.gain.linearRampToValueAtTime(0.09,t+0.004);og.gain.exponentialRampToValueAtTime(0.0001,t+0.065);og.gain.linearRampToValueAtTime(0,t+0.07);o.connect(og);og.connect(musicBus);o.start(t);o.stop(t+0.075);}
function sHihat(t,open){var dur=open?0.14:0.028;var nb=Math.floor(audioCtx.sampleRate*dur),buf=audioCtx.createBuffer(1,nb,audioCtx.sampleRate),d=buf.getChannelData(0);for(var i=0;i<nb;i++)d[i]=Math.random()*2-1;var src=audioCtx.createBufferSource(),f=audioCtx.createBiquadFilter(),g=audioCtx.createGain();f.type='highpass';f.frequency.value=7500;src.buffer=buf;g.gain.setValueAtTime(0,t);g.gain.linearRampToValueAtTime(mDyn.hihatVol,t+0.003);g.gain.exponentialRampToValueAtTime(0.0001,t+dur);g.gain.linearRampToValueAtTime(0,t+dur+0.003);src.connect(f);f.connect(g);g.connect(musicBus);src.start(t);src.stop(t+dur+0.006);}
function sBass(freq,t,ft){var o=audioCtx.createOscillator(),f=audioCtx.createBiquadFilter(),g=audioCtx.createGain();o.type='sawtooth';o.frequency.value=freq;f.type='lowpass';f.frequency.value=480+ft*80;f.Q.value=1.8;var dur=MSTEP*(1/ft)*1.7;g.gain.setValueAtTime(0,t);g.gain.linearRampToValueAtTime(mDyn.bassVol,t+0.006);g.gain.exponentialRampToValueAtTime(0.0001,t+dur);g.gain.linearRampToValueAtTime(0,t+dur+0.004);o.connect(f);f.connect(g);g.connect(musicBus);o.start(t);o.stop(t+dur+0.006);}
function sLead(freq,t,ft){var o=audioCtx.createOscillator(),f=audioCtx.createBiquadFilter(),g=audioCtx.createGain();o.type='square';o.frequency.value=freq;f.type='lowpass';f.frequency.value=1800+ft*200;var dur=MSTEP*(1/ft)*1.2;g.gain.setValueAtTime(0,t);g.gain.linearRampToValueAtTime(mDyn.leadVol,t+0.005);g.gain.exponentialRampToValueAtTime(0.0001,t+dur);g.gain.linearRampToValueAtTime(0,t+dur+0.004);o.connect(f);f.connect(g);g.connect(musicBus);o.start(t);o.stop(t+dur+0.006);}
function scheduleMStep(step,time,ft){var bi=Math.floor(step/MBAR)%Mpseq.length,pi=Mpseq[bi],s=step%MBAR;if(MKICK[pi][s])sKick(time);if(MSNARE[pi][s])sSnare(time);if(MHIHAT[pi][s])sHihat(time,!!MOPEN[pi][s]);if(MBASS[pi][s])sBass(MBASS[pi][s],time,ft);if(MLEAD[pi][s])sLead(MLEAD[pi][s],time,ft);}
function tickMusic(){if(!mRunning||!audioCtx||!musicBus)return;var ft=mDyn.tempo,stepDur=MSTEP*(1/ft);while(mNextTime<audioCtx.currentTime+0.18){scheduleMStep(mStep,mNextTime,ft);mStep++;mNextTime+=stepDur;}}
function startMusicEngine(){if(mRunning||!audioCtx)return;mRunning=true;mStep=0;mNextTime=audioCtx.currentTime+0.05;}
function stopMusicEngine(){mRunning=false;}
// ═══════════════════════════════════════════════════
// SFX
// ═══════════════════════════════════════════════════
var arpNotes=[261.63,293.66,329.63,392.00,440.00,523.25],arpIdx=0;
function playCountdownNum(){if(!audioCtx)return;var t=audioCtx.currentTime;var o=audioCtx.createOscillator(),g=audioCtx.createGain();o.type='sine';o.frequency.setValueAtTime(280,t);o.frequency.exponentialRampToValueAtTime(55,t+0.22);g.gain.setValueAtTime(0,t);g.gain.linearRampToValueAtTime(0.38,t+0.004);g.gain.exponentialRampToValueAtTime(0.0001,t+0.22);g.gain.linearRampToValueAtTime(0,t+0.225);o.connect(g);g.connect(sfxBus);o.start(t);o.stop(t+0.23);makeNoise(1800,0.12,0.035,sfxBus,t);}
function playFightSound(){if(!audioCtx)return;var freqs=[220,330,440,554,659];for(var i=0;i<freqs.length;i++){(function(fr,delay){var t=audioCtx.currentTime+delay;makeOsc('sawtooth',fr,0.07,0.45,sfxBus,t);})(freqs[i],i*0.022);}}
function playArp(){if(!audioCtx)return;makeOsc('triangle',arpNotes[arpIdx%arpNotes.length],0.055,0.14,sfxBus);arpIdx++;}
function soundImpact(){if(!audioCtx)return;makeNoise(900,0.10,0.018,sfxBus);makeOsc('sine',80,0.07,0.055,sfxBus);}
function soundGood(){if(!audioCtx)return;makeOsc('sine',300+combo*8,0.055,0.09,sfxBus);}
function soundMiss(){if(!audioCtx)return;makeOsc('sawtooth',105,0.065,0.11,sfxBus);makeNoise(400,0.035,0.07,sfxBus);}
function updateApproach(prox){if(!audioCtx||!sfxBus)return;if(prox>0.25){if(!approachOsc){approachOsc=audioCtx.createOscillator();approachGain=audioCtx.createGain();approachOsc.type='sine';approachGain.gain.value=0;approachOsc.connect(approachGain);approachGain.connect(sfxBus);approachOsc.start();}approachOsc.frequency.value=160+prox*260;approachGain.gain.setTargetAtTime(prox*0.02,audioCtx.currentTime,0.05);}else if(approachOsc){approachGain.gain.setTargetAtTime(0,audioCtx.currentTime,0.05);}}
function soundEndDramatic(ok){stopMusicEngine();if(approachOsc){approachGain.gain.setTargetAtTime(0,audioCtx.currentTime,0.02);setTimeout(function(){try{approachOsc.stop();}catch(e){}approachOsc=null;},200);}if(!audioCtx)return;if(ok){var freqs=[220,277,330,440];for(var i=0;i<freqs.length;i++){(function(fr,d){setTimeout(function(){makeOsc('sine',fr,0.07,0.8,sfxBus);},d);})(freqs[i],i*90);}}else{var o=audioCtx.createOscillator(),g=audioCtx.createGain(),f=audioCtx.createBiquadFilter();f.type='lowpass';f.frequency.setValueAtTime(600,audioCtx.currentTime);f.frequency.exponentialRampToValueAtTime(70,audioCtx.currentTime+1.5);o.type='sawtooth';o.frequency.setValueAtTime(180,audioCtx.currentTime);o.frequency.exponentialRampToValueAtTime(55,audioCtx.currentTime+1.5);g.gain.setValueAtTime(0,audioCtx.currentTime);g.gain.linearRampToValueAtTime(0.07,audioCtx.currentTime+0.004);g.gain.exponentialRampToValueAtTime(0.0001,audioCtx.currentTime+1.5);g.gain.linearRampToValueAtTime(0,audioCtx.currentTime+1.505);o.connect(f);f.connect(g);g.connect(sfxBus);o.start();o.stop(audioCtx.currentTime+1.51);}}
// ═══════════════════════════════════════════════════
// TUTORIAL
// ═══════════════════════════════════════════════════
var TUT_STEPS=5;
var tutActive=!V.MindGameTutSeen;
var tutStep=0,tutTime=0,tutFadeIn=0;
var tutData=[
{title:'MIND BATTLE',sub:'How to play',body:'A ring contracts toward the target circle.\nClick at the exact moment the ring aligns\nwith the golden target to score points.',demo:'ring'},
{title:'SCORING ZONES',sub:'Precision matters',body:'PERFECT (gold center) — maximum points + time bonus\nGOOD (blue band) — standard points\nMISS (outside) — lose points and reset combo',demo:'zones'},
{title:'COMBOS & STREAKS',sub:'Chain your hits',body:'Consecutive hits build a combo multiplier:\nx1.5 at 3 hits · x2 at 5 · x3 at 8\n\nReach 5 / 10 / 15 combo for a STREAK BONUS:\n+time, invincibility, and screen effects.',demo:'combo'},
{title:'RING TYPES',sub:'Watch the colors',body:null,demo:'rings'},
{title:'YOUR STATS',sub:'What they change',body:null,demo:'stats'}
];
function roundRect(x,y,w,h,r){ctx.beginPath();ctx.moveTo(x+r,y);ctx.lineTo(x+w-r,y);ctx.quadraticCurveTo(x+w,y,x+w,y+r);ctx.lineTo(x+w,y+h-r);ctx.quadraticCurveTo(x+w,y+h,x+w-r,y+h);ctx.lineTo(x+r,y+h);ctx.quadraticCurveTo(x,y+h,x,y+h-r);ctx.lineTo(x,y+r);ctx.quadraticCurveTo(x,y,x+r,y);ctx.closePath();}
function drawTutDemo(type,cx,cy,dw,dh,ts){
ctx.save();
ctx.beginPath();ctx.rect(cx-dw/2,cy-dh/2,dw,dh);ctx.clip();
if(type==='ring'){
var TR2=dh*0.28,startR2=TR2*3.2,speed=startR2/2.8;
var ringR=startR2-(tutTime%2.8)*speed;if(ringR<TR2*0.6)ringR=startR2;
var gh=TR2*0.15,ph=TR2*0.04;
ctx.beginPath();ctx.arc(cx,cy,TR2,0,Math.PI*2);ctx.strokeStyle='rgba(125,211,252,0.25)';ctx.lineWidth=gh*2;ctx.stroke();
ctx.beginPath();ctx.arc(cx,cy,TR2,0,Math.PI*2);ctx.strokeStyle='rgba(251,191,36,0.5)';ctx.lineWidth=ph*2;ctx.stroke();
ctx.beginPath();ctx.arc(cx,cy,2.5,0,Math.PI*2);ctx.fillStyle='rgba(255,255,255,0.3)';ctx.fill();
var proximity=Math.max(0,1-Math.abs(ringR-TR2)/(gh*3));
ctx.beginPath();ctx.arc(cx,cy,Math.max(1,ringR),0,Math.PI*2);
ctx.strokeStyle='hsl(260,80%,68%)';ctx.lineWidth=2.5;ctx.shadowColor='#a78bfa';ctx.shadowBlur=12+proximity*18;ctx.stroke();ctx.shadowBlur=0;
if(proximity>0.5){ctx.globalAlpha=proximity;ctx.font='bold '+Math.round(dh*0.14)+'px monospace';ctx.textAlign='center';ctx.textBaseline='middle';ctx.fillStyle='#fbbf24';ctx.shadowColor='#fbbf24';ctx.shadowBlur=12;ctx.fillText('CLICK!',cx,cy+TR2+dh*0.18);ctx.shadowBlur=0;ctx.globalAlpha=1;}
}
else if(type==='zones'){
var TR2=dh*0.28,gh=TR2*0.18,ph=gh*0.28;
ctx.beginPath();ctx.arc(cx,cy,TR2+gh*3.5,0,Math.PI*2);ctx.strokeStyle='rgba(239,68,68,0.12)';ctx.lineWidth=gh*4;ctx.stroke();
ctx.beginPath();ctx.arc(cx,cy,TR2,0,Math.PI*2);ctx.strokeStyle='rgba(125,211,252,0.55)';ctx.lineWidth=gh*2;ctx.stroke();
ctx.beginPath();ctx.arc(cx,cy,TR2,0,Math.PI*2);ctx.strokeStyle='rgba(251,191,36,0.85)';ctx.lineWidth=ph*2;ctx.shadowColor='#fbbf24';ctx.shadowBlur=10;ctx.stroke();ctx.shadowBlur=0;
ctx.font='bold '+Math.round(dh*0.11)+'px monospace';ctx.textAlign='center';ctx.textBaseline='middle';
ctx.fillStyle='#fbbf24';ctx.fillText('PERFECT',cx,cy+TR2-gh*3.2);
ctx.fillStyle='#7dd3fc';ctx.fillText('GOOD',cx,cy+TR2+gh*1.2);
ctx.fillStyle='rgba(239,68,68,0.7)';ctx.fillText('MISS',cx,cy+TR2+gh*4.2);
ctx.beginPath();ctx.arc(cx,cy,TR2+gh*1.8,0,Math.PI*2);ctx.strokeStyle='rgba(167,139,250,0.5)';ctx.lineWidth=2;ctx.stroke();
}
else if(type==='combo'){
var combos=[1,2,3,4,5,6];
var idx=Math.floor(tutTime*1.4)%combos.length;
var displayCombo=combos[idx];
var mult=displayCombo>=8?3:displayCombo>=5?2:displayCombo>=3?1.5:1;
var col=displayCombo>=8?'#f87171':displayCombo>=5?'#fb923c':'#fbbf24';
ctx.font='bold '+Math.round(dh*0.44)+'px monospace';ctx.textAlign='center';ctx.textBaseline='middle';
ctx.fillStyle=col;ctx.shadowColor=col;ctx.shadowBlur=22;ctx.fillText(displayCombo,cx,cy-dh*0.1);ctx.shadowBlur=0;
ctx.font=Math.round(dh*0.14)+'px monospace';ctx.fillStyle='rgba(255,255,255,0.5)';ctx.fillText('hits',cx,cy+dh*0.22);
if(mult>1){ctx.font='bold '+Math.round(dh*0.18)+'px monospace';ctx.fillStyle=col;ctx.shadowColor=col;ctx.shadowBlur=14;ctx.fillText('× '+mult,cx,cy+dh*0.42);ctx.shadowBlur=0;}
var bw=dw*0.55,bx=cx-bw/2,by=cy-dh*0.46,bh=5;
ctx.fillStyle='rgba(255,255,255,0.08)';roundRect(bx,by,bw,bh,3);ctx.fill();
ctx.fillStyle=col;roundRect(bx,by,bw*(displayCombo/8),bh,3);ctx.fill();
}
else if(type==='rings'){
var ringtypes=[
{col:'hsl(260,78%,66%)',shadow:'#a78bfa',icon:'●',label:'NORMAL',sub:'Standard ring',lc:'rgba(200,190,230,0.85)'},
{col:'hsl(48,100%,62%)',shadow:'#fbbf24',icon:'★',label:'BONUS',sub:'+pts +time',lc:'#fbbf24'},
{col:'hsl(0,85%,60%)',shadow:'#ef4444',icon:'☠',label:'DANGER',sub:'Penalty on miss',lc:'#f87171'},
{col:'hsl(200,90%,65%)',shadow:'#38bdf8',icon:'⚡',label:'ACCEL',sub:'Speeds up',lc:'#7dd3fc'},
{col:'hsl(180,70%,60%)',shadow:'#2dd4bf',icon:'❄',label:'DECEL',sub:'Slows down',lc:'#5eead4'}
];
var cols=5,itemW=dw/cols;
var ringR=Math.min(itemW*0.28,dh*0.22);
var ringY=cy-dh*0.12;
for(var i=0;i<ringtypes.length;i++){
var rt=ringtypes[i];
var rx=cx-dw/2+itemW*(i+0.5);
var pulse=1+0.06*Math.sin(tutTime*2.2+i*1.1);
ctx.beginPath();ctx.arc(rx,ringY,ringR*pulse,0,Math.PI*2);
ctx.strokeStyle=rt.col;ctx.lineWidth=2;ctx.shadowColor=rt.shadow;ctx.shadowBlur=10;ctx.stroke();ctx.shadowBlur=0;
ctx.font='bold '+Math.round(ringR*0.7)+'px monospace';ctx.textAlign='center';ctx.textBaseline='middle';
ctx.fillStyle=rt.col;ctx.fillText(rt.icon,rx,ringY);
ctx.font='bold '+Math.round(itemW*0.13)+'px monospace';ctx.textBaseline='top';
ctx.fillStyle=rt.lc;ctx.fillText(rt.label,rx,ringY+ringR+6);
ctx.font=Math.round(itemW*0.105)+'px monospace';
ctx.fillStyle='rgba(200,190,220,0.55)';ctx.fillText(rt.sub,rx,ringY+ringR+6+Math.round(itemW*0.16));
}
}
// FIX: gap dynamique pour que tout tienne dans dh
else if(type==='stats'){
var rows=[
{
icon:'♥',label:'AFFECTION',col:'#f472b6',
lines:[
{t:'Every 10 pts → +0.5s time limit',h:false},
{t:'(up to +15s at 300 affection)',h:false},
{t:'Every 100 pts → -1 miss penalty',h:false},
{t:'High affection = more room for error',h:true}
]
},
{
icon:'✦',label:'PSYCHIC POWER',col:'#a78bfa',
lines:[
{t:'Scales corruption gained on success',h:false},
{t:'Formula: √(PP) ÷ 10 (max ×2)',h:false},
{t:'At PP 100 → ×1.0 At PP 400 → ×2.0',h:false},
{t:'Higher PP = deeper mind corruption',h:true}
]
}
];
var lineH=Math.round(dh*0.082);
var headerH=Math.round(dh*0.115);
var sectionH=headerH+4*lineH;
// gap dynamique : espace restant après les 2 sections, plafonné à 28
var gap=Math.max(8,Math.min(28,Math.floor(dh*0.92-sectionH*2)));
var totalH=sectionH*2+gap;
var startY=cy-totalH/2;
for(var ri=0;ri<rows.length;ri++){
var row=rows[ri];
var ry=startY+ri*(sectionH+gap);
ctx.font='bold '+Math.round(dh*0.108)+'px monospace';ctx.textAlign='left';ctx.textBaseline='top';
ctx.fillStyle=row.col;ctx.shadowColor=row.col;ctx.shadowBlur=8;
ctx.fillText(row.icon+' '+row.label,cx-dw*0.42,ry);ctx.shadowBlur=0;
for(var li=0;li<row.lines.length;li++){
var ln=row.lines[li];
ctx.font=(ln.h?'bold ':'')+Math.round(dh*0.079)+'px monospace';
ctx.fillStyle=ln.h?row.col:'rgba(200,190,220,0.6)';
ctx.fillText(ln.t,cx-dw*0.38,ry+headerH+li*lineH);
}
if(ri<rows.length-1){
var sepY=ry+sectionH+gap/2;
ctx.strokeStyle='rgba(167,139,250,0.15)';ctx.lineWidth=1;
ctx.beginPath();ctx.moveTo(cx-dw*0.42,sepY);ctx.lineTo(cx+dw*0.42,sepY);ctx.stroke();
}
}
}
ctx.restore();
}
function drawTutPanel(ts,dt){
tutTime+=dt;tutFadeIn=Math.min(1,tutFadeIn+dt*4);
var step=tutData[tutStep];
ctx.save();ctx.globalAlpha=tutFadeIn;
ctx.fillStyle='rgba(6,6,12,0.96)';ctx.fillRect(0,0,W,H);
for(var i=0;i<stars.length;i++){var st=stars[i];ctx.beginPath();ctx.arc(st.rx*W,st.ry*H,st.r,0,Math.PI*2);ctx.fillStyle='rgba(255,255,255,'+st.a.toFixed(2)+')';ctx.fill();}
var needsMore=step.demo==='rings'||step.demo==='stats';
var CW=Math.min(W*0.88,needsMore?600:520);
var CH=Math.min(H*0.84,needsMore?500:460);
var CX=(W-CW)/2,CY=(H-CH)/2;
ctx.fillStyle='rgba(15,10,30,0.92)';ctx.shadowColor='rgba(167,139,250,0.18)';ctx.shadowBlur=40;
roundRect(CX,CY,CW,CH,14);ctx.fill();ctx.shadowBlur=0;
ctx.strokeStyle='rgba(167,139,250,0.22)';ctx.lineWidth=1;roundRect(CX,CY,CW,CH,14);ctx.stroke();
var dotY=CY+18,dotSpacing=14,dotsW=(TUT_STEPS-1)*dotSpacing,dotX0=CX+CW/2-dotsW/2;
for(var i=0;i<TUT_STEPS;i++){ctx.beginPath();ctx.arc(dotX0+i*dotSpacing,dotY,i===tutStep?4:2.5,0,Math.PI*2);ctx.fillStyle=i===tutStep?npcColor:i<tutStep?'rgba(167,139,250,0.5)':'rgba(255,255,255,0.15)';ctx.fill();}
ctx.textAlign='center';ctx.textBaseline='middle';
ctx.font='bold '+Math.round(CW*0.072)+'px monospace';
ctx.fillStyle=npcColor;ctx.shadowColor=npcColor;ctx.shadowBlur=22;
ctx.fillText(step.title,W/2,CY+52);ctx.shadowBlur=0;
ctx.font=Math.round(CW*0.034)+'px monospace';ctx.fillStyle='rgba(251,191,36,0.7)';
ctx.fillText(step.sub.toUpperCase(),W/2,CY+78);
var DY=CY+100,DH=Math.round(CH*(needsMore?0.42:0.36));
drawTutDemo(step.demo,W/2,DY+DH/2,CW*0.9,DH,ts);
if(step.body){
var lines=step.body.split('\n'),ty=DY+DH+22;
for(var i=0;i<lines.length;i++){
if(lines[i]===''){ty+=8;continue;}
var isH=lines[i].indexOf('PERFECT')>=0||lines[i].indexOf('STREAK')>=0;
ctx.font=(isH?'bold ':'')+Math.round(CW*0.031)+'px monospace';
ctx.fillStyle=isH?'#e2d9ff':'rgba(200,190,220,0.72)';ctx.shadowBlur=0;
ctx.fillText(lines[i],W/2,ty);ty+=Math.round(CW*0.042);
}
}
var btnW=160,btnH=36,btnX=W/2-btnW/2,btnY=CY+CH-50;
var isLast=tutStep===TUT_STEPS-1,pulse=0.85+0.15*Math.sin(tutTime*3);
ctx.globalAlpha=tutFadeIn*pulse;
ctx.fillStyle=isLast?'rgba(167,139,250,0.22)':'rgba(167,139,250,0.14)';
ctx.strokeStyle=isLast?npcColor:'rgba(167,139,250,0.45)';
ctx.lineWidth=isLast?1.5:1;ctx.shadowColor=npcColor;ctx.shadowBlur=isLast?14:0;
roundRect(btnX,btnY,btnW,btnH,8);ctx.fill();roundRect(btnX,btnY,btnW,btnH,8);ctx.stroke();
ctx.shadowBlur=0;ctx.globalAlpha=tutFadeIn;
ctx.font='bold '+Math.round(btnH*0.38)+'px monospace';
ctx.fillStyle=isLast?'#c4b5fd':'rgba(200,190,230,0.75)';
ctx.fillText(isLast?'START BATTLE':'NEXT →',W/2,btnY+btnH/2+1);
ctx.restore();
}
function tutAdvance(){if(tutStep<TUT_STEPS-1){tutStep++;tutFadeIn=0.3;tutTime=0;}else{tutActive=false;V.MindGameTutSeen=true;}}
// ═══════════════════════════════════════════════════
// COUNTDOWN
// ═══════════════════════════════════════════════════
var cdPhase='press',cdTimer=0,cdScale=1.0,gameStarted=false;
function drawCountdown(ts){
if(cdPhase===-1)return;
ctx.save();
if(cdPhase==='press'){
ctx.fillStyle='rgba(0,0,0,.68)';ctx.fillRect(0,0,W,H);
ctx.textAlign='center';ctx.textBaseline='middle';
ctx.font='bold '+Math.round(H*.052)+'px monospace';
ctx.fillStyle=npcColor;ctx.shadowColor=npcColor;ctx.shadowBlur=40;
ctx.fillText('MIND BATTLE',W/2,H*.36);
ctx.font='bold '+Math.round(H*.02)+'px monospace';
ctx.fillStyle='rgba(200,200,200,.55)';ctx.shadowBlur=0;
ctx.fillText('VS '+(npc.name||V.MindNPCDisplay||'???').toUpperCase(),W/2,H*.45);
var b=.5+.5*Math.sin(ts*.0025);
ctx.globalAlpha=.4+b*.6;ctx.font='bold '+Math.round(H*.027)+'px monospace';
ctx.fillStyle='#fff';ctx.shadowColor='#fff';ctx.shadowBlur=18;
ctx.fillText('PRESS ANYWHERE',W/2,H*.57);ctx.globalAlpha=1;
}else if(cdPhase==='intro'){
ctx.fillStyle='rgba(0,0,0,.6)';ctx.fillRect(0,0,W,H);
}else if(typeof cdPhase==='number'&&cdPhase>=0){
ctx.fillStyle='rgba(0,0,0,.55)';ctx.fillRect(0,0,W,H);
var text=cdPhase===0?'FIGHT!':String(cdPhase);
var col=cdPhase===0?'#fbbf24':'#ffffff';
var size=Math.round(H*.25*cdScale);
ctx.font='bold '+size+'px monospace';ctx.textAlign='center';ctx.textBaseline='middle';
ctx.shadowColor=col;ctx.shadowBlur=100;ctx.globalAlpha=.3;ctx.fillStyle=col;ctx.fillText(text,W/2,H/2);
ctx.shadowBlur=50;ctx.globalAlpha=.65;ctx.fillText(text,W/2,H/2);
ctx.shadowBlur=0;ctx.globalAlpha=1;
ctx.strokeStyle=cdPhase===0?'rgba(251,191,36,.92)':'rgba(255,35,35,.92)';
ctx.lineWidth=Math.max(2,size*.055);ctx.strokeText(text,W/2,H/2);
ctx.fillStyle=col;ctx.shadowColor=col;ctx.shadowBlur=28;ctx.fillText(text,W/2,H/2);
}
ctx.restore();
}
// ═══════════════════════════════════════════════════
// GAME STATE
// ═══════════════════════════════════════════════════
var score=0,combo=0,missStreak=0,lastStreakReward=0;
var streakActive=false,streakTimer=0,nextIsDanger=false,chromaAmt=0;
var gameOver=false,doneRendering=false,hinted=false,lastTs=null,rafId=null;
var targets=[],rings=[],particles=[],floats=[],stars=[];
var diffLevel=0,globalHue=0;
var nextId=0,activeCount=0,freezeUntil=0;
var bgFlash={col:'#fff',alpha:0};
var endScreen={active:false,text:'',col:'',alpha:0,scale:.4};
var shakeAmt=0;
var bgPulses=[],bgPulseTimer=0,bgBeams=[],bgBeamTimer=0;
var bgGridPulse=0,bgAuroraIntensity=0;
for(var si=0;si<90;si++)stars.push({rx:Math.random(),ry:Math.random(),r:.3+Math.random()*1.3,a:Math.random()*.4+.04,da:(Math.random()-.5)*.013,vx:0,vy:0});
// ═══════════════════════════════════════════════════
// HELPERS
// ═══════════════════════════════════════════════════
function rndPos(){return{x:MARGIN+Math.random()*(W-MARGIN*2),y:HUD+MARGIN+Math.random()*(H-HUD-MARGIN*2-20)};}
function travelTime(){var base=2.4-mindNorm*.4;return Math.max(.8,base-diffLevel*(.08-mindNorm*.04));}
function baseRingSpeed(){return(startR-TR)/travelTime()+(Math.random()-.5)*14;}
function comboMult(){return combo>=8?3:combo>=5?2:combo>=3?1.5:1;}
function getTarget(tid){for(var i=0;i<targets.length;i++)if(targets[i].id===tid)return targets[i];return null;}
function closestRing(tid){var best=null,bd=Infinity;for(var i=0;i<rings.length;i++){if(rings[i].tid===tid&&!rings[i].dead&&!rings[i].missed){var d=Math.abs(rings[i].r-TR);if(d<bd){bd=d;best=rings[i];}}}return{dist:bd,ring:best};}
function pushStars(cx,cy,force){for(var i=0;i<stars.length;i++){var dx=stars[i].rx*W-cx,dy=stars[i].ry*H-cy,d=Math.sqrt(dx*dx+dy*dy);if(d<180){var f=(1-d/180)*force;stars[i].vx+=(dx/(d||1))*f;stars[i].vy+=(dy/(d||1))*f;}}}
function burstAt(x,y,col,n,spd){for(var i=0;i<n;i++){var a=Math.random()*Math.PI*2,s=(spd||100)+Math.random()*120;particles.push({x:x,y:y,vx:Math.cos(a)*s,vy:Math.sin(a)*s-30,r:1.4+Math.random()*3.2,col:col,life:1,ml:.45+Math.random()*.55,type:'dot'});}}
function lightningAt(x,y,col,n){for(var i=0;i<n;i++){var a=Math.random()*Math.PI*2;particles.push({type:'lightning',x:x,y:y,a:a,col:col,len:20+Math.random()*55,segs:4+Math.floor(Math.random()*4),jitter:8+Math.random()*12,life:1,ml:.14+Math.random()*.18});}}
function fragmentRing(ring){var n=7;for(var i=0;i<n;i++){var ang=i/n*Math.PI*2,vel=38+Math.random()*55,ao=ang+(Math.random()-.5)*.55,sx=ring.tx+Math.cos(ang)*ring.r,sy=ring.ty+Math.sin(ang)*ring.r;particles.push({type:'arc',x:sx,y:sy,r:TR*.11,startAng:ang,arcLen:Math.PI*2/n*.72,vx:Math.cos(ao)*vel,vy:Math.sin(ao)*vel,vr:(Math.random()-.5)*80,col:'hsl('+ring.hue+',82%,66%)',life:1,ml:.32+Math.random()*.22});}}
function shockwave(x,y,col,spd){particles.push({type:'wave',x:x,y:y,r:TR*.85,speed:spd||100,alpha:1,col:col});}
function addFloat(txt,col,big,tx,ty){floats.push({text:txt,col:col,x:(tx||W/2)+(Math.random()-.5)*36,y:(ty||H/2)-12,life:1,ml:1.15,big:big||false});}
function triggerShake(px){shakeAmt=Math.max(shakeAmt,px);}
function spawnBgPulse(x,y,col,fast){bgPulses.push({x:x||W/2,y:y||H/2,r:fast?TR*2:TR,speed:fast?220:110,maxR:Math.max(W,H)*0.85,alpha:fast?0.18:0.09,col:col||'167,139,250'});}
function spawnBgBeam(){var side=Math.floor(Math.random()*4),x1,y1,x2,y2;if(side===0){x1=Math.random()*W;y1=0;x2=Math.random()*W;y2=H;}else if(side===1){x1=0;y1=Math.random()*H;x2=W;y2=Math.random()*H;}else if(side===2){x1=Math.random()*W;y1=H;x2=Math.random()*W;y2=0;}else{x1=W;y1=Math.random()*H;x2=0;y2=Math.random()*H;}bgBeams.push({x1:x1,y1:y1,x2:x2,y2:y2,life:1,ml:0.35+Math.random()*0.2,col:combo>=8?'239,68,68':combo>=5?'251,146,60':'167,139,250'});}
function spawnTarget(){var pos=rndPos(),tid=nextId++;activeCount++;targets.push({id:tid,x:pos.x,y:pos.y,alive:true,fadeIn:0,fadeOut:0,dying:false});var kr=Math.random();var kind=nextIsDanger?'danger':kr<.06?'bonus':kr<.12?'danger':kr<.22?'accel':kr<.32?'decel':'normal';nextIsDanger=false;var spd=baseRingSpeed(),hue=kind==='bonus'?48:kind==='danger'?0:(globalHue+150+Math.random()*130);rings.push({tid:tid,tx:pos.x,ty:pos.y,r:startR,speed:spd,baseSpeed:spd,age:0,kind:kind,hue:hue,alpha:1,trail:[],dead:false,missed:false,fragged:false});}
function killTarget(tid){for(var i=0;i<targets.length;i++){if(targets[i].id===tid&&targets[i].alive){targets[i].alive=false;targets[i].dying=true;targets[i].fadeOut=1;activeCount=Math.max(0,activeCount-1);break;}}if(!gameOver)setTimeout(function(){if(!gameOver)maybeSpawn();},500);}
function maybeSpawn(){if(activeCount<1)spawnTarget();}
function setScore(s){score=s;var el=document.getElementById('mg-score');if(!el)return;el.textContent=score+' pts';el.style.color=score<0?'#f87171':score>10?'#fbbf24':'#fff';el.classList.remove('pop');void el.offsetWidth;el.classList.add('pop');}
function updateComboEl(){var el=document.getElementById('mg-combo');if(!el)return;if(combo>=3){el.textContent='COMBO x'+comboMult();el.style.color=combo>=8?'#f87171':combo>=5?'#fb923c':'#fbbf24';el.classList.add('show');}else{el.textContent='';el.classList.remove('show');}}
function checkStreakReward(){var ms=[5,10,15],bonusT=[3,5,8];for(var i=0;i<ms.length;i++){if(combo>=ms[i]&&lastStreakReward<ms[i]){lastStreakReward=ms[i];streakActive=true;streakTimer=1.3;var pts=bonusT[i];timeLeft=Math.min(timeLeft+pts,MAX_TIME+60);addFloat('🔥 STREAK x'+ms[i]+'! +'+pts+'s','#fbbf24',true,W/2,H/3);bgFlash={col:'#fbbf24',alpha:2};burstAt(W/2,H/2,'#fbbf24',65,210);shockwave(W/2,H/2,'#fbbf24',230);shockwave(W/2,H/2,'rgba(251,191,36,.28)',120);lightningAt(W/2,H/2,'#fde68a',14);pushStars(W/2,H/2,1.8);triggerShake(14);if(audioCtx)makeOsc('square',660,0.06,0.4,sfxBus);break;}}}
// ═══════════════════════════════════════════════════
// CLICK
// ═══════════════════════════════════════════════════
function onClick(e){
ensureAudio();
if(tutActive){tutAdvance();if(audioCtx)makeOsc('sine',440+tutStep*80,0.04,0.07,sfxBus);return;}
if(cdPhase==='press'){startMusicEngine();cdPhase='intro';cdTimer=.32;return;}
if(cdPhase!==-1)return;
if(!gameStarted||gameOver)return;
if(!hinted){hinted=true;var h=document.getElementById('mg-hint');if(h)h.style.opacity='0';}
var rect=canvas.getBoundingClientRect();
var mx=(e.clientX-rect.left)*(W/rect.width),my=(e.clientY-rect.top)*(H/rect.height);
var best=null,bd=Infinity;
for(var i=0;i<rings.length;i++){var ring=rings[i];if(ring.dead||ring.missed)continue;var t=getTarget(ring.tid);if(!t||!t.alive)continue;var dx=mx-ring.tx,dy=my-ring.ty;if(Math.sqrt(dx*dx+dy*dy)<startR+10){var rd=Math.abs(ring.r-TR);if(rd<bd){bd=rd;best=ring;}}}
if(!best){triggerShake(3);return;}
var tx=best.tx,ty=best.ty,ph=perfHalf(),isB=best.kind==='bonus',isD=best.kind==='danger';
var effDist=streakActive?0:bd;best.dead=true;
if(isD&&effDist>goodHalf*1.2){combo=0;missStreak++;updateComboEl();arpIdx=0;if(missStreak>=3){nextIsDanger=true;missStreak=0;}var pen=Math.min(5,Math.max(2,Math.floor(bd/(TR*.18))));setScore(Math.max(-30,score-pen));burstAt(tx,ty,'#f87171',22,88);shockwave(tx,ty,'#ef4444',100);lightningAt(tx,ty,'#f87171',8);addFloat('💀 TRAP -'+pen,'#f87171',true,tx,ty);triggerShake(18);chromaAmt=.85;soundMiss();pushStars(tx,ty,.7);killTarget(best.tid);return;}
var mult=comboMult();
if(effDist<=ph){combo++;missStreak=0;updateComboEl();checkStreakReward();var sI=combo>=8?12:combo>=5?8:combo>=3?5:3;triggerShake(sI);var pts=isB?Math.round(3*mult):Math.round(2*mult),tsB=isB?2:1;setScore(score+pts);timeLeft=Math.min(timeLeft+tsB,MAX_TIME+60);goodHalf=Math.max(MIN_GOOD,goodHalf-TR*.0045);freezeUntil=performance.now()+80;chromaAmt=.95;bgFlash={col:isB?'#fbbf24':'#a78bfa',alpha:1.2};spawnBgPulse(tx,ty,isB?'251,191,36':combo>=8?'239,68,68':combo>=5?'251,146,60':'167,139,250',combo>=3);if(combo>=5)spawnBgBeam();burstAt(tx,ty,isB?'#fde68a':'#fbbf24',isB?55:42,150);shockwave(tx,ty,'#fbbf24',162);shockwave(tx,ty,'rgba(251,191,36,.2)',88);lightningAt(tx,ty,isB?'#fbbf24':'#c4b5fd',10);addFloat((isB?'★ BONUS':'✦ PERFECT')+(mult>1?' x'+mult:''),'#fbbf24',true,tx,ty);addFloat('+'+pts+' +'+tsB+'s','#fde68a',false,tx,ty+30);floats.push({text:'+'+pts,col:'#fbbf24',x:W/2,y:H/2,life:1,ml:.5,big:true});soundImpact();playArp();pushStars(tx,ty,1.3);killTarget(best.tid);}
else if(effDist<=goodHalf){combo++;missStreak=0;updateComboEl();checkStreakReward();var sI=combo>=5?4:2;triggerShake(sI);var pts=isB?Math.round(2*mult):Math.round(1*mult);setScore(score+pts);goodHalf=Math.max(MIN_GOOD,goodHalf-TR*.003);bgFlash={col:'#7dd3fc',alpha:.7};spawnBgPulse(tx,ty,'125,211,252',false);if(combo>=5)spawnBgBeam();burstAt(tx,ty,'#7dd3fc',22,115);shockwave(tx,ty,'#7dd3fc',96);lightningAt(tx,ty,'#7dd3fc',4);addFloat('GOOD +'+pts+(mult>1?' x'+mult:''),'#7dd3fc',false,tx,ty);soundGood();playArp();pushStars(tx,ty,.6);killTarget(best.tid);}
else{var pen=Math.min(isD?5:3,Math.max(1,Math.floor(bd/(TR*.26))));if(isD)pen=Math.min(5,pen*2);combo=0;missStreak++;updateComboEl();arpIdx=0;if(missStreak>=3){nextIsDanger=true;missStreak=0;}setScore(Math.max(-30,score-pen));burstAt(tx,ty,'#f87171',14,72);lightningAt(tx,ty,'#f87171',5);addFloat('-'+pen,'#f87171',false,tx,ty);triggerShake(5+pen*2);if(pen>=2)chromaAmt=Math.max(chromaAmt,.45);soundMiss();killTarget(best.tid);}
}
// ═══════════════════════════════════════════════════
// END
// ═══════════════════════════════════════════════════
function endGame(){
if(gameOver)return;gameOver=true;
var ppM=Math.min(2,Math.sqrt(Math.max(0,pp))/10),affM=1+(affNorm*.2),diffM=1/(1+mind/150);
var corGain=Math.round(Math.min(50,Math.max(0,score)*ppM*affM*diffM)),ok=score>0&&corGain>0;
soundEndDramatic(ok);
if(ok){npc.cor=Math.min(500,(Number(npc.cor)||0)+corGain);V.MindCalcMsg='Success. <em>+'+corGain+' corruption</em>';endScreen={active:true,text:'MIND BROKEN',col:'#a78bfa',alpha:0,scale:.4};burstAt(W/2,H/2,'#a78bfa',65,185);shockwave(W/2,H/2,'#a78bfa',85);lightningAt(W/2,H/2,'#c4b5fd',18);pushStars(W/2,H/2,2.5);}
else{V.Stress=(Number(V.Stress)||0)+5;var al=Math.min(5,Math.abs(score));npc.aff=Math.max(0,aff-al);V.MindCalcMsg='Failure. <em>+5 stress</em>'+(al>0?' <em>-'+al+' affection</em>':'');endScreen={active:true,text:'RESISTED',col:'#f87171',alpha:0,scale:.4};}
V.MindNPC=npc;V.MindCalcRoll=score;V.MindCalcPct=corGain||0;
setTimeout(function(){doneRendering=true;if(rafId)cancelAnimationFrame(rafId);Engine.play('MindResult');},2000);
}
// ═══════════════════════════════════════════════════
// DRAW TARGET
// ═══════════════════════════════════════════════════
function drawTarget(t,ts){
var alpha=t.dying?t.fadeOut:Math.min(1,t.fadeIn*3);if(alpha<=0)return;
var cr=closestRing(t.id),dist=cr.dist,ring=cr.ring;
var kind=ring?ring.kind:'normal',prox=ring?Math.max(0,1-dist/(goodHalf*5)):0;
var pulse=1+prox*.07*Math.sin(ts*.022),isB=kind==='bonus',isD=kind==='danger',ph=perfHalf(),mult=comboMult();
ctx.globalAlpha=alpha;
var bg=ctx.createRadialGradient(t.x,t.y,0,t.x,t.y,TR*2.2*pulse);bg.addColorStop(0,isD?'rgba(200,30,30,.14)':isB?'rgba(251,191,36,.12)':'rgba(76,29,149,.11)');bg.addColorStop(1,'transparent');ctx.fillStyle=bg;ctx.fillRect(t.x-TR*2.5,t.y-TR*2.5,TR*5,TR*5);
if(prox>.28){ctx.save();ctx.beginPath();for(var i=0;i<=60;i++){var ang=i/60*Math.PI*2,dw=Math.sin(ang*9+ts*.017)*prox*4.5,rx=t.x+Math.cos(ang)*(TR+dw),ry=t.y+Math.sin(ang)*(TR+dw);if(i===0)ctx.moveTo(rx,ry);else ctx.lineTo(rx,ry);}ctx.strokeStyle='rgba(255,200,100,'+(prox*.12)+')';ctx.lineWidth=1.5;ctx.stroke();ctx.restore();}
ctx.save();ctx.beginPath();ctx.arc(t.x,t.y,TR*pulse,0,Math.PI*2);ctx.strokeStyle=isD?'rgba(239,68,68,.22)':'rgba(255,255,255,.18)';ctx.lineWidth=goodHalf*2;ctx.shadowBlur=4+prox*12;ctx.shadowColor='rgba(255,255,255,.04)';ctx.stroke();ctx.restore();
ctx.save();ctx.beginPath();ctx.arc(t.x,t.y,TR*pulse,0,Math.PI*2);ctx.strokeStyle=isD?'rgba(239,68,68,.62)':isB?'rgba(251,191,36,.72)':'rgba(251,191,36,.58)';ctx.lineWidth=ph*2;ctx.shadowColor=isD?'#ef4444':'#fbbf24';ctx.shadowBlur=12+prox*20;ctx.stroke();ctx.restore();
ctx.beginPath();ctx.arc(t.x,t.y,2.5,0,Math.PI*2);ctx.fillStyle='rgba(255,255,255,.28)';ctx.fill();
if(mult>1){ctx.save();ctx.font='bold 11px monospace';ctx.textAlign='center';ctx.fillStyle=mult>=3?'#f87171':mult>=2?'#fb923c':'#fbbf24';ctx.globalAlpha=alpha*.9;ctx.shadowColor=ctx.fillStyle;ctx.shadowBlur=8;ctx.fillText('x'+mult,t.x,t.y+TR+goodHalf+14);ctx.restore();}
ctx.globalAlpha=1;
}
// ═══════════════════════════════════════════════════
// DRAW BACKGROUND FX
// ═══════════════════════════════════════════════════
function drawBgFx(ts,dt){
var targetAurora=gameStarted?Math.min(0.55,combo*0.055):0;bgAuroraIntensity+=(targetAurora-bgAuroraIntensity)*dt*1.8;
if(bgAuroraIntensity>0.004){var hue=combo>=8?0:combo>=5?28:260;var ag=ctx.createRadialGradient(W/2,H/2,Math.min(W,H)*0.28,W/2,H/2,Math.max(W,H)*0.82);ag.addColorStop(0,'transparent');ag.addColorStop(1,'hsla('+hue+',85%,55%,'+bgAuroraIntensity+')');ctx.fillStyle=ag;ctx.fillRect(0,0,W,H);}
if(gameStarted&&combo>=3){bgGridPulse+=dt*3;var gi=Math.min(0.06,(combo-2)*0.012)*Math.abs(Math.sin(bgGridPulse));if(gi>0.002){ctx.save();ctx.globalAlpha=gi;ctx.strokeStyle='rgba(167,139,250,1)';ctx.lineWidth=0.5;var gs=Math.round(Math.max(W,H)/9);for(var gx=0;gx<W;gx+=gs){ctx.beginPath();ctx.moveTo(gx,0);ctx.lineTo(gx,H);ctx.stroke();}for(var gy=0;gy<H;gy+=gs){ctx.beginPath();ctx.moveTo(0,gy);ctx.lineTo(W,gy);ctx.stroke();}ctx.restore();}}
for(var i=bgPulses.length-1;i>=0;i--){var bp=bgPulses[i];bp.r+=bp.speed*dt;bp.alpha*=0.97;if(bp.alpha<0.004||bp.r>bp.maxR){bgPulses.splice(i,1);continue;}ctx.beginPath();ctx.arc(bp.x,bp.y,bp.r,0,Math.PI*2);ctx.strokeStyle='rgba('+bp.col+','+bp.alpha.toFixed(3)+')';ctx.lineWidth=1.2;ctx.stroke();if(bp.r>40){ctx.beginPath();ctx.arc(bp.x,bp.y,bp.r*0.72,0,Math.PI*2);ctx.strokeStyle='rgba('+bp.col+','+(bp.alpha*0.4).toFixed(3)+')';ctx.lineWidth=0.7;ctx.stroke();}}
for(var i=bgBeams.length-1;i>=0;i--){var bb=bgBeams[i];bb.life-=dt/bb.ml;if(bb.life<=0){bgBeams.splice(i,1);continue;}ctx.save();ctx.globalAlpha=bb.life*0.06;ctx.strokeStyle='rgb('+bb.col+')';ctx.lineWidth=0.8;ctx.shadowColor='rgb('+bb.col+')';ctx.shadowBlur=8;ctx.beginPath();ctx.moveTo(bb.x1,bb.y1);var mx=(bb.x1+bb.x2)/2+(Math.random()-.5)*80,my=(bb.y1+bb.y2)/2+(Math.random()-.5)*80;ctx.quadraticCurveTo(mx,my,bb.x2,bb.y2);ctx.stroke();ctx.restore();}
if(combo>=8){ctx.save();ctx.globalAlpha=Math.min(0.055,(combo-7)*0.008);for(var sy=0;sy<H;sy+=4){ctx.fillStyle='rgba(0,0,0,1)';ctx.fillRect(0,sy,W,2);}ctx.restore();}
}
// ═══════════════════════════════════════════════════
// DRAW
// ═══════════════════════════════════════════════════
function draw(ts,dt){
if(ts<freezeUntil)return;
ctx.clearRect(0,0,W,H);ctx.save();
if(shakeAmt>0.2){ctx.translate((Math.random()*2-1)*shakeAmt,(Math.random()*2-1)*shakeAmt*0.7);shakeAmt=Math.max(0,shakeAmt-dt*(shakeAmt*8+12));}else{shakeAmt=0;}
ctx.fillStyle='#06060c';ctx.fillRect(0,0,W,H);
if(bgFlash.alpha>0){ctx.fillStyle=bgFlash.col;ctx.globalAlpha=bgFlash.alpha*.09;ctx.fillRect(0,0,W,H);ctx.globalAlpha=1;bgFlash.alpha=Math.max(0,bgFlash.alpha-dt*4.5);}
if(combo>=3){var ca=Math.min(.1,combo*.009),cc=combo>=8?'rgba(239,68,68,'+ca+')':combo>=5?'rgba(251,146,60,'+ca+')':'rgba(251,191,36,'+ca+')';var cg=ctx.createRadialGradient(W/2,H/2,0,W/2,H/2,Math.max(W,H)*.65);cg.addColorStop(0,cc);cg.addColorStop(1,'transparent');ctx.fillStyle=cg;ctx.fillRect(0,0,W,H);}
drawBgFx(ts,dt);
for(var i=0;i<stars.length;i++){var st=stars[i];st.a+=st.da;if(st.a<.03||st.a>.45)st.da*=-1;st.rx+=(st.vx||0)*dt/W;st.ry+=(st.vy||0)*dt/H;st.vx=(st.vx||0)*.9;st.vy=(st.vy||0)*.9;if(st.rx<0)st.rx+=1;if(st.rx>1)st.rx-=1;if(st.ry<0)st.ry+=1;if(st.ry>1)st.ry-=1;ctx.beginPath();ctx.arc(st.rx*W,st.ry*H,st.r,0,Math.PI*2);ctx.fillStyle='rgba(255,255,255,'+st.a.toFixed(2)+')';ctx.fill();}
if(gameStarted&&timeLeft<MAX_TIME*.3){var vigI=(1-timeLeft/(MAX_TIME*.3))*.5,vg=ctx.createRadialGradient(W/2,H/2,Math.min(W,H)*.25,W/2,H/2,Math.max(W,H)*.8);vg.addColorStop(0,'transparent');vg.addColorStop(1,'rgba(160,0,0,'+vigI+')');ctx.fillStyle=vg;ctx.fillRect(0,0,W,H);}
if(streakActive&&streakTimer>0){ctx.fillStyle='rgba(251,191,36,'+Math.min(.055,streakTimer*.04)+')';ctx.fillRect(0,0,W,H);}
for(var i=0;i<targets.length;i++)drawTarget(targets[i],ts);
ctx.save();ctx.globalCompositeOperation='lighter';
for(var i=0;i<rings.length;i++){var ring=rings[i];var al=ring.dead?Math.max(0,ring.alpha):ring.missed?ring.alpha*.4:1;if(al<=0)continue;var isB2=ring.kind==='bonus',isD2=ring.kind==='danger',th=isB2?'hsla(48,90%,65%,':isD2?'hsla(0,85%,60%,':'hsla('+ring.hue+',80%,65%,';for(var t=0;t<ring.trail.length;t++){var ta=(t/ring.trail.length)*.10*al;ctx.beginPath();ctx.arc(ring.tx,ring.ty,Math.max(.5,ring.trail[t]),0,Math.PI*2);ctx.strokeStyle=th+ta+')';ctx.lineWidth=2;ctx.stroke();}}
ctx.restore();
for(var i=0;i<rings.length;i++){var ring=rings[i];var al=ring.dead?Math.max(0,ring.alpha):ring.missed?ring.alpha*.4:1;if(al<=0)continue;var isB2=ring.kind==='bonus',isD2=ring.kind==='danger',rC=isB2?'hsl(48,100%,62%)':isD2?'hsl(0,85%,60%)':'hsl('+ring.hue+',78%,66%)',rG=isB2?'#fbbf24':isD2?'#ef4444':'hsl('+ring.hue+',85%,62%)',rI=isB2?'hsl(48,100%,90%)':isD2?'hsl(0,100%,85%)':'hsl('+ring.hue+',100%,93%)';ctx.save();ctx.globalAlpha=al;ctx.beginPath();ctx.arc(ring.tx,ring.ty,Math.max(.5,ring.r),0,Math.PI*2);ctx.strokeStyle=rC;ctx.lineWidth=2.5;ctx.shadowColor=rG;ctx.shadowBlur=24;ctx.stroke();ctx.lineWidth=.8;ctx.strokeStyle=rI;ctx.shadowBlur=4;ctx.stroke();if(comboMult()>1){ctx.font='bold 10px monospace';ctx.textAlign='center';ctx.fillStyle=rC;ctx.globalAlpha=al*.65;ctx.fillText('x'+comboMult(),ring.tx,ring.ty-ring.r-6);}ctx.restore();}
for(var i=particles.length-1;i>=0;i--){var p=particles[i];if(p.type==='wave'){p.r+=p.speed*dt;p.alpha-=dt*2.2;if(p.alpha<=0){particles.splice(i,1);continue;}ctx.save();ctx.beginPath();ctx.arc(p.x,p.y,p.r,0,Math.PI*2);ctx.strokeStyle=p.col;ctx.globalAlpha=p.alpha;ctx.lineWidth=2;ctx.shadowColor=p.col;ctx.shadowBlur=9;ctx.stroke();ctx.restore();}else if(p.type==='arc'){p.life-=dt/p.ml;if(p.life<=0){particles.splice(i,1);continue;}p.x+=p.vx*dt;p.y+=p.vy*dt;p.startAng+=p.vr*dt;ctx.save();ctx.globalAlpha=p.life*.85;ctx.beginPath();ctx.arc(p.x,p.y,Math.max(.5,p.r),p.startAng,p.startAng+p.arcLen);ctx.strokeStyle=p.col;ctx.lineWidth=2;ctx.shadowColor=p.col;ctx.shadowBlur=8;ctx.stroke();ctx.restore();}else if(p.type==='lightning'){p.life-=dt/p.ml;if(p.life<=0){particles.splice(i,1);continue;}ctx.save();ctx.globalAlpha=p.life*.88;ctx.strokeStyle=p.col;ctx.lineWidth=1.2;ctx.shadowColor=p.col;ctx.shadowBlur=7;ctx.beginPath();var lx=p.x,ly=p.y,sl=p.len/p.segs;ctx.moveTo(lx,ly);for(var s=0;s<p.segs;s++){lx+=Math.cos(p.a)*sl+(Math.random()-.5)*p.jitter;ly+=Math.sin(p.a)*sl+(Math.random()-.5)*p.jitter;ctx.lineTo(lx,ly);}ctx.stroke();ctx.restore();}else{p.life-=dt/p.ml;if(p.life<=0){particles.splice(i,1);continue;}p.x+=p.vx*dt;p.y+=p.vy*dt;p.vy+=130*dt;ctx.beginPath();ctx.arc(p.x,p.y,p.r*Math.max(0,p.life),0,Math.PI*2);ctx.fillStyle=p.col;ctx.globalAlpha=p.life*.88;ctx.fill();ctx.globalAlpha=1;}}
for(var i=floats.length-1;i>=0;i--){var f=floats[i];f.life-=dt/f.ml;if(f.life<=0){floats.splice(i,1);continue;}f.y-=34*dt;ctx.save();ctx.font=(f.big?'bold 21px':'bold 12px')+' monospace';ctx.textAlign='center';ctx.fillStyle=f.col;ctx.globalAlpha=Math.min(1,f.life*1.7);ctx.shadowColor=f.col;ctx.shadowBlur=14;ctx.fillText(f.text,f.x,f.y);ctx.restore();}
if(endScreen.active){endScreen.alpha=Math.min(1,endScreen.alpha+dt*2);endScreen.scale=Math.min(1.5,endScreen.scale+dt*1.8);ctx.save();ctx.globalAlpha=endScreen.alpha*.7;ctx.fillStyle='rgba(0,0,0,.8)';ctx.fillRect(0,0,W,H);ctx.globalAlpha=endScreen.alpha;ctx.font='bold '+Math.round(TR*endScreen.scale*1.1)+'px monospace';ctx.textAlign='center';ctx.textBaseline='middle';ctx.fillStyle=endScreen.col;ctx.shadowColor=endScreen.col;ctx.shadowBlur=50;ctx.fillText(endScreen.text,W/2,H/2);ctx.restore();}
ctx.restore();
if(chromaAmt>0){var coff=chromaAmt*7;ctx.save();ctx.globalCompositeOperation='screen';for(var i=0;i<rings.length;i++){var ring=rings[i];var al=ring.dead?ring.alpha:ring.missed?ring.alpha*.4:1;if(al<=0)continue;ctx.beginPath();ctx.arc(ring.tx-coff,ring.ty,Math.max(.5,ring.r),0,Math.PI*2);ctx.strokeStyle='rgb(255,0,0)';ctx.lineWidth=2.5;ctx.globalAlpha=chromaAmt*.16*al;ctx.stroke();ctx.beginPath();ctx.arc(ring.tx+coff,ring.ty,Math.max(.5,ring.r),0,Math.PI*2);ctx.strokeStyle='rgb(0,255,255)';ctx.lineWidth=2.5;ctx.globalAlpha=chromaAmt*.16*al;ctx.stroke();}ctx.restore();chromaAmt=Math.max(0,chromaAmt-dt*2.8);}
var ne=document.getElementById('mg-npcname');
if(ne){if(combo>=3){var gi=Math.min(1,combo/10),gs=5+gi*24;ne.style.textShadow='0 0 '+gs+'px '+npcColor;ne.style.color=combo>=8?'#f87171':combo>=5?'#fb923c':npcColor;}else{ne.style.textShadow='none';ne.style.color=npcColor;}}
if(!tutActive)drawCountdown(ts);
}
// ═══════════════════════════════════════════════════
// LOOP
// ═══════════════════════════════════════════════════
function loop(ts){
if(!lastTs)lastTs=ts;
var dt=Math.min((ts-lastTs)/1000,.05);lastTs=ts;
for(var i=0;i<stars.length;i++){var st=stars[i];st.a+=st.da;if(st.a<.03||st.a>.45)st.da*=-1;st.rx+=(st.vx||0)*dt/W;st.ry+=(st.vy||0)*dt/H;st.vx=(st.vx||0)*.9;st.vy=(st.vy||0)*.9;if(st.rx<0)st.rx+=1;if(st.rx>1)st.rx-=1;if(st.ry<0)st.ry+=1;if(st.ry>1)st.ry-=1;}
if(tutActive){ctx.clearRect(0,0,W,H);drawTutPanel(ts,dt);rafId=requestAnimationFrame(loop);return;}
tickMusic();
if(audioCtx&&Math.random()<.08)updateBusGains();
if(cdPhase!==(-1)){
if(cdPhase==='press'){draw(ts,dt);rafId=requestAnimationFrame(loop);return;}
if(cdPhase==='intro'){cdTimer-=dt;if(cdTimer<=0){cdPhase=3;cdScale=2.0;cdTimer=.72;playCountdownNum();}draw(ts,dt);rafId=requestAnimationFrame(loop);return;}
cdTimer-=dt;cdScale=Math.max(1.0,cdScale-dt*6);
if(cdTimer<=0){if(cdPhase>0){cdPhase--;cdTimer=cdPhase===0?.65:.72;cdScale=2.0;if(cdPhase===0)playFightSound();else playCountdownNum();}else{cdPhase=-1;gameStarted=true;var h=document.getElementById('mg-hint');if(h)h.style.opacity='1';spawnTarget();}}
draw(ts,dt);rafId=requestAnimationFrame(loop);return;
}
if(!gameOver){
timeLeft-=dt;if(timeLeft<=0){timeLeft=0;draw(ts,dt);endGame();return;}
diffLevel=Math.min(5,((MAX_TIME-timeLeft)/MAX_TIME)*5);globalHue+=dt*14;
if(streakActive){streakTimer-=dt;if(streakTimer<=0){streakActive=false;streakTimer=0;}}
if(combo>=3&&Math.random()<Math.min(.7,(combo-2)*.07)*dt*1.5)goodHalf=Math.max(MIN_GOOD,goodHalf-TR*.0022);
bgPulseTimer-=dt;if(bgPulseTimer<=0){bgPulseTimer=Math.max(0.5,1.4-combo*0.07);spawnBgPulse(W/2,H/2,combo>=8?'239,68,68':combo>=5?'251,146,60':'167,139,250',false);}
if(combo>=5){bgBeamTimer-=dt;if(bgBeamTimer<=0){bgBeamTimer=0.6+Math.random()*0.5;spawnBgBeam();}}
var maxP=0;for(var i=0;i<rings.length;i++){if(!rings[i].dead&&!rings[i].missed){var p2=Math.max(0,1-Math.abs(rings[i].r-TR)/(goodHalf*5));if(p2>maxP)maxP=p2;}}
updateApproach(maxP);updateMDyn(combo,timeLeft,MAX_TIME,missStreak);maybeSpawn();
for(var i=targets.length-1;i>=0;i--){var t=targets[i];if(t.alive)t.fadeIn=Math.min(1,t.fadeIn+dt*3);if(t.dying){t.fadeOut=Math.max(0,t.fadeOut-dt*5);if(t.fadeOut<=0)targets.splice(i,1);}}
for(var i=rings.length-1;i>=0;i--){var r=rings[i];if(!r.dead&&!r.missed){if(r.kind==='accel')r.speed=Math.min(r.baseSpeed*2.4,r.baseSpeed*(.4+r.age*.8));else if(r.kind==='decel')r.speed=Math.max(r.baseSpeed*.25,r.baseSpeed*(1.9-r.age*.8));r.age+=dt;if(Math.random()<.17){var ang2=Math.random()*Math.PI*2,sx=r.tx+Math.cos(ang2)*r.r,sy=r.ty+Math.sin(ang2)*r.r,sc=r.kind==='bonus'?'hsl(48,100%,72%)':r.kind==='danger'?'hsl(0,90%,65%)':'hsl('+r.hue+',90%,75%)';particles.push({x:sx,y:sy,vx:Math.cos(ang2)*(10+Math.random()*22),vy:Math.sin(ang2)*(10+Math.random()*22),r:.5+Math.random()*1.1,col:sc,life:1,ml:.09+Math.random()*.11,type:'dot'});}r.trail.push(r.r);if(r.trail.length>9)r.trail.shift();r.r-=r.speed*dt;if(r.r<TR-goodHalf-6){if(!r.fragged){r.fragged=true;fragmentRing(r);}r.missed=true;r.alpha=1;var tg=getTarget(r.tid);if(tg&&tg.alive){var pen2=missPenalty();combo=0;missStreak++;updateComboEl();arpIdx=0;if(missStreak>=3){nextIsDanger=true;missStreak=0;}setScore(Math.max(-30,score-pen2));if(pen2>0){burstAt(tg.x,tg.y,'#f87171',10,60);addFloat('-'+pen2,'#f87171',false,tg.x,tg.y);}triggerShake(7);soundMiss();pushStars(tg.x,tg.y,.5);killTarget(r.tid);}}}else{if(r.dead&&!r.fragged&&r.alpha<.65){r.fragged=true;fragmentRing(r);}r.alpha-=dt*(r.dead?6:2.5);if(r.alpha<=0)rings.splice(i,1);}}
var tb=document.getElementById('mg-timerbar');if(tb){tb.style.width=Math.max(0,timeLeft/MAX_TIME*100)+'%';tb.style.background=timeLeft>MAX_TIME*.6?'#4ade80':timeLeft>MAX_TIME*.3?'#facc15':'#f87171';}
}
draw(ts,dt);if(!doneRendering)rafId=requestAnimationFrame(loop);
}
canvas.addEventListener('click',onClick);
rafId=requestAnimationFrame(loop);
$(document).one(':passagestart',function(){
doneRendering=true;gameOver=true;if(rafId)cancelAnimationFrame(rafId);
canvas.removeEventListener('click',onClick);stopMusicEngine();
if(approachOsc){try{approachGain.gain.setTargetAtTime(0,audioCtx.currentTime,0.01);setTimeout(function(){try{approachOsc.stop();}catch(e){}},100);}catch(e){}}
});
})();});
<</script>><<set $ShowTopUiBar = false>><<set $ShowBottomUiBar = false>><div id="cs2-root"></div><<script>>
(function(){
/* STATE */
var state = {
tab: "dashboard",
selected_tournament: null,
selected_team: null,
selected_mode: "faceit",
selected_map: null,
selected_skill: null,
match_running: false,
last_match: null,
last_tournament: null,
post_match: null,
interactive_choice: null,
choice_result: null,
scout_offer: null,
messages: [],
unread: 0,
_contract_warned: false,
_refrag_warned: false
};
var P = State.variables.PlayerCS2;
var CS = setup.CS2;
/* UTILS */
function esc(s){ return String(s==null?"":s).replace(/[&<>"']/g,function(c){return({"&":"&","<":"<",">":">",'"':""","'":"'"}[c]);}); }
function fmt(n){ return Number(n||0).toLocaleString(); }
function pct(a,b){ return b>0?Math.round((a/b)*100):0; }
/* PUSH MESSAGE */
function pushMessage(msg){
var day = State.variables.Day || 0;
msg.day = day;
msg.unread = true;
msg.resolved= false;
state.messages.push(msg);
state.unread++;
}
/* RENDER ROOT */
function render(){
var root = document.getElementById("cs2-root");
if(!root) return;
P = State.variables.PlayerCS2;
root.innerHTML =
buildShell(
buildSidebar() +
'<div class="cs2-main">' +
buildTab() +
'</div>'
);
bind(root);
}
function buildShell(inner){
return '<div class="cs2-wrap">'+inner+'</div>';
}
/* SIDEBAR */
function buildSidebar(){
var tabs = [
{ id:"dashboard", icon:"⬡", label:"Dashboard" },
{ id:"play", icon:"▶", label:"Play" },
{ id:"career", icon:"🏷", label:"Career" },
{ id:"tournaments", icon:"🏆", label:"Tournaments" },
{ id:"rankings", icon:"◈", label:"Rankings" },
{ id:"teams", icon:"◉", label:"Teams" },
{ id:"inbox", icon:"✉", label:"Inbox" }
];
var lvl_cur = P.level ? P.level.current : 1;
var xp_cur = P.xp ? P.xp.total : 0;
var xp_needed = CS.XP_PER_LEVEL ? CS.XP_PER_LEVEL(lvl_cur) : 500;
var lvl_pct = Math.round((xp_cur / xp_needed) * 100);
var sp_left = P.level ? P.level.skill_points : 0;
var elo_cur = P.elo ? P.elo.current : 800;
var fl_lvl = P.faceit ? P.faceit.lvl : 1;
return '<div class="cs2-sidebar">'+
'<div class="cs2-sidebar-brand">CS2<span>SIM</span></div>'+
'<div class="cs2-close-btn" id="cs2-close">✕ Exit</div>'+
'<div class="cs2-sidebar-player">'+
'<div class="cs2-fl-badge cs2-fl-'+fl_lvl+'">'+esc(fl_lvl)+'</div>'+
'<div class="cs2-sidebar-info">'+
'<div class="cs2-sidebar-name">'+esc(P.username)+'</div>'+
'<div class="cs2-sidebar-sub">'+esc(P.role ? P.role.toUpperCase() : "FREE")+' • LVL '+lvl_cur+'</div>'+
'</div>'+
'</div>'+
'<div class="cs2-xp-bar-wrap">'+
'<div class="cs2-xp-bar-label-row">'+
'<span class="cs2-xp-bar-lbl">LEVEL '+lvl_cur+'</span>'+
(sp_left > 0 ? '<span class="cs2-sp-alert" data-goto="spendpoints">'+sp_left+' pt'+(sp_left>1?'s':'')+' ▶</span>' : '')+
'</div>'+
'<div class="cs2-xp-bar-track"><div class="cs2-xp-bar-fill" style="width:'+lvl_pct+'%"></div></div>'+
'<div class="cs2-xp-label">'+fmt(xp_cur)+' / '+fmt(xp_needed)+' XP</div>'+
'</div>'+
'<div class="cs2-xp-bar-wrap">'+
'<div class="cs2-xp-bar-label-row">'+
'<span class="cs2-xp-bar-lbl">ELO</span>'+
'<span class="cs2-xp-bar-lbl cs2-elo-val">'+esc(elo_cur)+'</span>'+
'</div>'+
'<div class="cs2-elo-track">'+
'<div class="cs2-elo-fill" style="width:'+Math.round((elo_cur/3000)*100)+'%"></div>'+
'</div>'+
'<div class="cs2-xp-label">FL '+fl_lvl+' • '+fmt(P.faceit ? P.faceit.xpToNext : 0)+' to next</div>'+
'</div>'+
'<nav class="cs2-nav">'+
tabs.map(function(t){
return '<div class="cs2-nav-item'+(state.tab===t.id?' isActive':'')+'" data-tab="'+t.id+'">'+
'<span class="cs2-nav-icon">'+t.icon+'</span>'+
'<span class="cs2-nav-label">'+t.label+'</span>'+
(t.id==="inbox" && state.unread > 0 ?
'<span class="cs2-inbox-badge">'+state.unread+'</span>' : '')+
'</div>';
}).join('')+
'</nav>'+
'<div class="cs2-sidebar-footer">'+
(P.career.team_id ?
'<div class="cs2-team-pill">'+esc(CS.getTeam(P.career.team_id).tag)+'</div>' :
'<div class="cs2-team-pill free">FREE AGENT</div>'
)+
'<div class="cs2-moral-row">'+
'<span class="cs2-moral-label">Moral</span>'+
'<div class="cs2-moral-track"><div class="cs2-moral-fill" style="width:'+P.moral+'%"></div></div>'+
'<span class="cs2-moral-num">'+Math.round(P.moral)+'</span>'+
'</div>'+
'<div class="cs2-moral-row">'+
'<span class="cs2-moral-label">Fatigue</span>'+
'<div class="cs2-moral-track"><div class="cs2-fatigue-fill" style="width:'+P.fatigue+'%"></div></div>'+
'<span class="cs2-moral-num">'+Math.round(P.fatigue)+'</span>'+
'</div>'+
'</div>'+
'</div>';
}
/* TABS */
function buildTab(){
if(state.tab==="dashboard") return buildDashboard();
if(state.tab==="play") return buildPlay();
if(state.tab==="result") return buildResult();
if(state.tab==="spendpoints") return buildSpendPoints();
if(state.tab==="career") return buildCareer();
if(state.tab==="tournaments") return buildTournaments();
if(state.tab==="rankings") return buildRankings();
if(state.tab==="teams") return buildTeams();
if(state.tab==="inbox") return buildInbox();
return "";
}
/* ================================================================
DASHBOARD
================================================================ */
function buildDashboard(){
var s = P.stats;
var day = State.variables.Day || 0;
var stat_cards = [
{ label:"Rating", value: s.rating || "1.00", sub:"HLTV-style" },
{ label:"K/D", value: s.kd || "0.00", sub:"Kill / Death" },
{ label:"ADR", value: s.adr || "0", sub:"Avg Damage / Round" },
{ label:"Matches", value: fmt(s.matches_played), sub:"Played" },
{ label:"Win Rate", value: pct(s.matches_won, s.matches_played)+"%", sub:fmt(s.matches_won)+" wins" },
{ label:"Clutches", value: pct(s.clutches_won, s.clutches_total)+"%", sub:s.clutches_won+"/"+s.clutches_total }
];
var skills_html = Object.keys(P.skills).map(function(sk){
var val = P.skills[sk].val;
return '<div class="cs2-skill-row">'+
'<div class="cs2-skill-name">'+esc(sk.charAt(0).toUpperCase()+sk.slice(1))+'</div>'+
'<div class="cs2-skill-bar-wrap"><div class="cs2-skill-bar-fill" style="width:'+val+'%"></div></div>'+
'<div class="cs2-skill-val">'+Math.round(val)+'</div>'+
'</div>';
}).join('');
var team_html = P.career.team_id ?
(function(){
var t = CS.getTeam(P.career.team_id);
return '<div class="cs2-dash-team">'+
'<div class="cs2-dash-team-tag">'+esc(t.tag)+'</div>'+
'<div class="cs2-dash-team-info">'+
'<div class="cs2-dash-team-name">'+esc(t.name)+'</div>'+
'<div class="cs2-dash-team-sub">Tier '+t.tier+' • '+esc(t.region)+(P.career.benched?' • <span style="color:rgb(230,87,99)">BENCHED</span>':' • Active')+'</div>'+
'<div class="cs2-dash-team-salary">$'+fmt(P.career.salary)+' / month</div>'+
'</div>'+
'</div>';
})() :
'<div class="cs2-dash-freeagent">Free Agent — Play matches to get scouted.</div>';
var last_match_html = "";
if(state.last_match){
var m = state.last_match;
last_match_html =
'<div class="cs2-section-title"><span class="cs2-section-bar"></span>LAST MATCH</div>'+
'<div class="cs2-last-match cs2-result-'+m.result+'">'+
'<div class="cs2-lm-score">'+m.score_player+' — '+m.score_enemy+'</div>'+
'<div class="cs2-lm-meta">'+esc(m.map)+(m.overtime?' • OT x'+m.overtime:'')+'</div>'+
'<div class="cs2-lm-result">'+m.result.toUpperCase()+'</div>'+
'</div>';
}
return '<div class="cs2-page">'+
'<div class="cs2-page-head"><div class="cs2-page-title">Dashboard</div><div class="cs2-page-sub">Day '+fmt(day)+'</div></div>'+
team_html+
'<div class="cs2-section-title"><span class="cs2-section-bar"></span>PERFORMANCE</div>'+
'<div class="cs2-stat-grid">'+
stat_cards.map(function(c){
return '<div class="cs2-stat-card">'+
'<div class="cs2-stat-val">'+esc(c.value)+'</div>'+
'<div class="cs2-stat-label">'+esc(c.label)+'</div>'+
'<div class="cs2-stat-sub">'+esc(c.sub)+'</div>'+
'</div>';
}).join('')+
'</div>'+
'<div class="cs2-section-title"><span class="cs2-section-bar"></span>COMBAT SKILLS</div>'+
'<div class="cs2-skills-panel">'+skills_html+'</div>'+
last_match_html+
'</div>';
}
/* ================================================================
PLAY
================================================================ */
function buildPlay(){
if(state.interactive_choice) return buildChoiceScreen();
if(state.match_running) return buildMatchRunning();
var modes = [
{ id:"faceit", icon:"⬡", label:"FaceIT Match", desc:"Ranked match. Gain ELO + XP based on performance.", color:"rgb(230,87,99)" },
{ id:"practice", icon:"◎", label:"Practice Match", desc:"Unranked. XP gain, no ELO change.", color:"rgba(255,255,255,.4)" },
{ id:"workshop", icon:"◈", label:"Workshop / Refrag", desc:"Targeted skill training. Choose what to improve."+(P.refrag_sub?" +Refrag bonus.":""), color:"rgba(255,180,50,.9)" }
];
var map_html = P.map_pool.map(function(m){
var active = state.selected_map === m ? ' isActive' : '';
return '<div class="cs2-map-chip'+active+'" data-map="'+esc(m)+'">'+esc(CS.MAPS[m]?CS.MAPS[m].name:m)+'</div>';
}).join('');
var workshop_html = "";
if(state.selected_mode === "workshop"){
workshop_html =
'<div class="cs2-section-title"><span class="cs2-section-bar"></span>CHOOSE SKILL TO TRAIN</div>'+
'<div class="cs2-skill-select-grid">'+
Object.keys(P.skills).map(function(sk){
return '<div class="cs2-skill-select-card'+(state.selected_skill===sk?' isActive':'')+'" data-skill="'+sk+'">'+
'<div class="cs2-skill-select-name">'+esc(sk.charAt(0).toUpperCase()+sk.slice(1))+'</div>'+
'<div class="cs2-skill-select-val">'+Math.round(P.skills[sk].val)+'</div>'+
'</div>';
}).join('')+
'</div>';
}
return '<div class="cs2-page">'+
'<div class="cs2-page-head"><div class="cs2-page-title">Play</div><div class="cs2-page-sub">Choose your game mode</div></div>'+
'<div class="cs2-mode-grid">'+
modes.map(function(m){
return '<div class="cs2-mode-card'+(state.selected_mode===m.id?' isActive':'')+'" data-mode="'+m.id+'" style="--mode-color:'+m.color+'">'+
'<div class="cs2-mode-icon">'+m.icon+'</div>'+
'<div class="cs2-mode-label">'+m.label+'</div>'+
'<div class="cs2-mode-desc">'+m.desc+'</div>'+
'</div>';
}).join('')+
'</div>'+
'<div class="cs2-section-title"><span class="cs2-section-bar"></span>MAP POOL</div>'+
'<div class="cs2-map-pool">'+map_html+'</div>'+
workshop_html+
'<div class="cs2-play-actions">'+
'<div class="cs2-btn cs2-btn-primary" id="cs2-play-btn">'+
(state.selected_mode==="workshop" ? "TRAIN" : "FIND MATCH")+
'</div>'+
'</div>'+
'</div>';
}
function buildMatchRunning(){
return '<div class="cs2-page cs2-page-center">'+
'<div class="cs2-spinner"></div>'+
'<div class="cs2-running-title">Simulating match...</div>'+
'<div class="cs2-running-sub">Results will appear shortly.</div>'+
'</div>';
}
function buildChoiceScreen(){
var c = state.interactive_choice;
var ch = CS.CHOICES[c.choice_id];
if(!ch) return "";
return '<div class="cs2-page cs2-page-choice">'+
'<div class="cs2-choice-context">'+esc(c.context || "")+'</div>'+
'<div class="cs2-choice-title">'+esc(ch.title)+'</div>'+
'<div class="cs2-choice-options">'+
ch.options.map(function(o){
var risk_pct = Math.round((o.risk||0)*100);
var skill_eff = o.skill ? Math.round(CS.effectiveSkill(P, o.skill)) : null;
return '<div class="cs2-choice-card" data-choice="'+esc(c.choice_id)+'" data-option="'+esc(o.id)+'">'+
'<div class="cs2-choice-card-top">'+
'<div class="cs2-choice-label">'+esc(o.label)+'</div>'+
(o.skill?'<div class="cs2-choice-skill">'+esc(o.skill)+' '+skill_eff+'</div>':'<div class="cs2-choice-skill free">No skill check</div>')+
'</div>'+
'<div class="cs2-choice-desc">'+esc(o.desc)+'</div>'+
(o.risk>0?'<div class="cs2-choice-risk">Risk '+risk_pct+'%</div>':'<div class="cs2-choice-risk safe">Safe action</div>')+
'</div>';
}).join('')+
'</div>'+
'</div>';
}
/* ================================================================
RESULT SCREEN
================================================================ */
function buildResult(){
var pm = state.post_match;
if(!pm) return '<div class="cs2-page"><div class="cs2-empty">No result.</div></div>';
var match = pm.match;
var xp_rep = pm.xp_report || {};
var elo_rep = pm.elo_report || {};
var result_banner = "";
if(match){
result_banner =
'<div class="cs2-result-banner cs2-result-'+match.result+'">'+
'<div class="cs2-rb-score">'+match.score_player+' — '+match.score_enemy+'</div>'+
'<div class="cs2-rb-map">'+esc(match.map)+(match.overtime?' • OT×'+match.overtime:'')+'</div>'+
'<div class="cs2-rb-label">'+match.result.toUpperCase()+'</div>'+
'</div>';
}
var elo_html = "";
if(pm.type === "faceit" && elo_rep.elo_change !== undefined){
var sign = elo_rep.elo_change >= 0 ? "+" : "";
var ecol = elo_rep.elo_change >= 0 ? "rgb(100,220,120)" : "rgb(230,87,99)";
elo_html =
'<div class="cs2-result-elo-row">'+
'<div class="cs2-rel-label">ELO</div>'+
'<div class="cs2-rel-change" style="color:'+ecol+'">'+sign+elo_rep.elo_change+'</div>'+
'<div class="cs2-rel-current">→ '+P.elo.current+' ELO (FL'+P.faceit.lvl+')</div>'+
'</div>';
}
var levelup_html = "";
if(xp_rep.leveled_up){
levelup_html =
'<div class="cs2-levelup-banner">'+
'<div class="cs2-lu-icon">⬆</div>'+
'<div class="cs2-lu-text">Level Up! <strong>Level '+P.level.current+'</strong></div>'+
'<div class="cs2-lu-pts">+'+xp_rep.skill_points_earned+' skill point'+(xp_rep.skill_points_earned>1?'s':'')+'</div>'+
'</div>';
}
var xp_breakdown = Object.keys(xp_rep.xp_gained || {}).filter(function(k){
return (xp_rep.xp_gained[k]||0) > 0;
}).map(function(cat){
var bar_w = CS.clamp(Math.round((xp_rep.xp_gained[cat]/50)*100), 2, 100);
return '<div class="cs2-xp-cat-row">'+
'<div class="cs2-xp-cat-name">'+esc(cat.charAt(0).toUpperCase()+cat.slice(1))+'</div>'+
'<div class="cs2-xp-cat-bar-wrap"><div class="cs2-xp-cat-bar-fill" style="width:'+bar_w+'%"></div></div>'+
'<div class="cs2-xp-cat-val">+'+xp_rep.xp_gained[cat]+' XP</div>'+
'</div>';
}).join('');
var stats_html = "";
if(match){
var s = P.stats;
stats_html =
'<div class="cs2-section-title"><span class="cs2-section-bar"></span>MATCH STATS</div>'+
'<div class="cs2-match-stats-grid">'+
'<div class="cs2-ms-card"><div class="cs2-ms-val">'+s.rating+'</div><div class="cs2-ms-label">Rating</div></div>'+
'<div class="cs2-ms-card"><div class="cs2-ms-val">'+s.kd+'</div><div class="cs2-ms-label">K/D</div></div>'+
'<div class="cs2-ms-card"><div class="cs2-ms-val">'+s.adr+'</div><div class="cs2-ms-label">ADR</div></div>'+
'</div>';
}
/* Scout → redirige vers inbox maintenant */
var scout_html = "";
if(pm.scout_notified){
scout_html =
'<div class="cs2-scout-notif">'+
'<div class="cs2-scout-icon">🔍</div>'+
'<div class="cs2-scout-text"><strong>A team has shown interest!</strong> Check your inbox.</div>'+
'<div class="cs2-btn cs2-btn-primary" data-goto="inbox">Open Inbox</div>'+
'</div>';
}
var has_points = P.level && P.level.skill_points > 0;
return '<div class="cs2-page">'+
'<div class="cs2-page-head">'+
'<div class="cs2-page-title">Match Result</div>'+
'<div class="cs2-page-sub">'+esc((pm.type||"").toUpperCase())+'</div>'+
'</div>'+
result_banner+
elo_html+
levelup_html+
(xp_breakdown ?
'<div class="cs2-section-title"><span class="cs2-section-bar"></span>XP GAINED</div>'+
'<div class="cs2-xp-breakdown">'+xp_breakdown+'</div>'+
'<div class="cs2-xp-total-row">Total: <strong>'+xp_rep.total_xp+' XP</strong> • Next level: <strong>'+P.xp.to_next_level+' XP</strong></div>'
: '')+
stats_html+
scout_html+
'<div class="cs2-result-actions">'+
(has_points?
'<div class="cs2-btn cs2-btn-primary cs2-sp-pulse" data-goto="spendpoints">Spend '+P.level.skill_points+' Skill Point'+(P.level.skill_points>1?'s':'')+'</div>':'')+
'<div class="cs2-btn cs2-btn-secondary" data-goto="play">Play Again</div>'+
'<div class="cs2-btn cs2-btn-secondary" data-goto="dashboard">Dashboard</div>'+
'</div>'+
'</div>';
}
/* ================================================================
SPEND SKILL POINTS
================================================================ */
function buildSpendPoints(){
var cats = [
{ key:"skills", label:"Combat Skills", items: P.skills },
{ key:"weapons", label:"Weapon Mastery", items: P.weapons },
{ key:"maps", label:"Map Knowledge", items: P.maps },
{ key:"utility_mastery", label:"Utility Mastery", items: P.utility_mastery }
];
var points_left = P.level ? P.level.skill_points : 0;
var sections = cats.filter(function(cat){ return cat.items; }).map(function(cat){
var items_html = Object.keys(cat.items).map(function(k){
var item = cat.items[k];
var gain = Math.max(1, Math.round(10 - item.val / 15));
var can_buy = points_left > 0;
return '<div class="cs2-sp-card'+(can_buy?'':' disabled')+'">'+
'<div class="cs2-sp-card-top">'+
'<div class="cs2-sp-name">'+esc(k.replace("de_","").replace(/_/g," ").toUpperCase())+'</div>'+
'<div class="cs2-sp-val">'+Math.round(item.val)+'</div>'+
'</div>'+
'<div class="cs2-sp-bar-wrap"><div class="cs2-sp-bar-fill" style="width:'+item.val+'%"></div></div>'+
'<div class="cs2-sp-gain">+'+gain+' per point</div>'+
(can_buy?
'<div class="cs2-btn cs2-btn-primary cs2-sp-btn" data-spcat="'+esc(cat.key)+'" data-spkey="'+esc(k)+'">Upgrade</div>':
'<div class="cs2-btn cs2-btn-disabled">No points</div>'
)+
'</div>';
}).join('');
return '<div class="cs2-sp-section">'+
'<div class="cs2-section-title"><span class="cs2-section-bar"></span>'+esc(cat.label.toUpperCase())+'</div>'+
'<div class="cs2-sp-grid">'+items_html+'</div>'+
'</div>';
}).join('');
return '<div class="cs2-page">'+
'<div class="cs2-page-head">'+
'<div class="cs2-page-title">Skill Points</div>'+
'<div class="cs2-page-sub cs2-sp-counter">'+points_left+' point'+(points_left!==1?'s':'')+' available</div>'+
'</div>'+
'<div class="cs2-sp-hint">Each point permanently increases a stat. Returns diminish as values get higher.</div>'+
sections+
'<div class="cs2-result-actions">'+
(points_left > 0 ?
'<div class="cs2-sp-remaining">'+points_left+' point'+(points_left!==1?'s':'')+' remaining</div>' :
'<div class="cs2-sp-done">✓ All points spent</div>'
)+
'<div class="cs2-btn cs2-btn-secondary" data-goto="dashboard">Continue</div>'+
'</div>'+
'</div>';
}
/* ================================================================
CAREER
================================================================ */
function buildCareer(){
var has_team = !!P.career.team_id;
var team = has_team ? CS.getTeam(P.career.team_id) : null;
var day = State.variables.Day || 0;
var contract_html = "";
if(has_team && P.career.current_contract){
var c = P.career.current_contract;
var days_left = Math.max(0, (c.end_day||0) - day);
contract_html =
'<div class="cs2-section-title"><span class="cs2-section-bar"></span>CONTRACT</div>'+
'<div class="cs2-contract-panel">'+
'<div class="cs2-contract-row"><span>Team</span><strong>'+esc(team.name)+'</strong></div>'+
'<div class="cs2-contract-row"><span>Salary</span><strong>$'+fmt(P.career.salary)+' / month</strong></div>'+
'<div class="cs2-contract-row"><span>Perf Bonus</span><strong>$'+fmt(c.perf_bonus||0)+'</strong></div>'+
'<div class="cs2-contract-row"><span>Buyout</span><strong>$'+fmt(c.buyout||0)+'</strong></div>'+
'<div class="cs2-contract-row"><span>Days Left</span><strong>'+fmt(days_left)+'</strong></div>'+
(P.career.benched?'<div class="cs2-contract-bench">⚠ Currently benched — 50% salary</div>':'')+
(c.no_bench_clause?'<div class="cs2-contract-clause">✓ No-bench clause active</div>':'')+
'</div>'+
'<div class="cs2-career-actions">'+
'<div class="cs2-btn cs2-btn-secondary" data-career="negotiate_salary">Negotiate Salary</div>'+
'<div class="cs2-btn cs2-btn-secondary" data-career="negotiate_bench">Request No-Bench Clause</div>'+
'<div class="cs2-btn cs2-btn-danger" data-career="buyout">Activate Buyout</div>'+
(P.career.benched?'<div class="cs2-btn cs2-btn-primary" data-career="unbench">Request Return</div>':'')+
'</div>';
}
var free_agent_html = !has_team ?
'<div class="cs2-freeagent-panel">'+
'<div class="cs2-freeagent-icon">◎</div>'+
'<div class="cs2-freeagent-title">Free Agent</div>'+
'<div class="cs2-freeagent-sub">Keep playing matches to get scouted by teams.</div>'+
'<div class="cs2-freeagent-requirements">'+
CS.SCOUT_THRESHOLDS.map(function(t){
var ok_lvl = P.faceit.lvl >= t.min_faceit_lvl;
var ok_rat = P.stats.rating >= t.min_rating;
var ok_mat = P.stats.matches_played >= t.min_matches;
var all_ok = ok_lvl && ok_rat && ok_mat;
return '<div class="cs2-req-row'+(all_ok?' met':'')+'">'+
'<div class="cs2-req-tier">Tier '+t.tier+'</div>'+
'<div class="cs2-req-checks">'+
'<span class="'+(ok_lvl?'ok':'nok')+'">FL'+t.min_faceit_lvl+'</span>'+
'<span class="'+(ok_rat?'ok':'nok')+'">'+t.min_rating+' rating</span>'+
'<span class="'+(ok_mat?'ok':'nok')+'">'+t.min_matches+' matches</span>'+
'</div>'+
'</div>';
}).join('')+
'</div>'+
'</div>' : "";
var pc_html =
'<div class="cs2-section-title"><span class="cs2-section-bar"></span>PC SETUP</div>'+
'<div class="cs2-pc-grid">'+
['cpu','gpu','ram'].map(function(k){
return '<div class="cs2-pc-card">'+
'<div class="cs2-pc-label">'+k.toUpperCase()+'</div>'+
'<div class="cs2-pc-bar-wrap"><div class="cs2-pc-bar-fill" style="width:'+P.pc[k]+'%"></div></div>'+
'<div class="cs2-pc-val">'+P.pc[k]+'</div>'+
'</div>';
}).join('')+
'<div class="cs2-pc-card"><div class="cs2-pc-label">HZ</div><div class="cs2-pc-val large">'+P.pc.hz+'</div></div>'+
'<div class="cs2-pc-card"><div class="cs2-pc-label">PING</div><div class="cs2-pc-val large'+(P.pc.ping>60?' bad':'')+'">'+P.pc.ping+'ms</div></div>'+
'<div class="cs2-pc-card"><div class="cs2-pc-label">XP MULT</div><div class="cs2-pc-val large">'+Math.round(CS.pcMultiplier(P.pc)*100)+'%</div></div>'+
'</div>'+
'<div class="cs2-career-actions">'+
'<div class="cs2-btn cs2-btn-secondary" data-career="upgrade_gpu">Upgrade GPU</div>'+
'<div class="cs2-btn cs2-btn-secondary" data-career="upgrade_cpu">Upgrade CPU</div>'+
'<div class="cs2-btn cs2-btn-secondary" data-career="upgrade_hz">Higher Hz Monitor</div>'+
'</div>';
var refrag_html =
'<div class="cs2-section-title"><span class="cs2-section-bar"></span>REFRAG SUBSCRIPTION</div>'+
'<div class="cs2-refrag-panel'+(P.refrag_sub?' active':'')+'">'+
'<div class="cs2-refrag-status">'+(P.refrag_sub?'✓ Active — +'+P.refrag_bonus+'% XP bonus':'✗ Inactive')+'</div>'+
'<div class="cs2-refrag-desc">Unlock targeted training in Workshop mode with XP bonus.</div>'+
(!P.refrag_sub?'<div class="cs2-btn cs2-btn-primary" data-career="buy_refrag">Subscribe ($30/month)</div>':'')+
'</div>';
return '<div class="cs2-page">'+
'<div class="cs2-page-head"><div class="cs2-page-title">Career</div><div class="cs2-page-sub">Manage your professional path</div></div>'+
free_agent_html+
contract_html+
pc_html+
refrag_html+
'</div>';
}
/* ================================================================
TOURNAMENTS
================================================================ */
function buildTournaments(){
var day = State.variables.Day || 0;
var available = CS.getAvailableTournaments(P, day);
var list_html = available.length > 0 ?
available.map(function(t){
var sel = state.selected_tournament === t.id;
var days_until = t.start_day - day;
return '<div class="cs2-tourn-card'+(sel?' isActive':'')+'" data-tourn="'+esc(t.id)+'">'+
'<div class="cs2-tourn-card-top">'+
'<div class="cs2-tourn-tier cs2-tier-'+t.tier+'">T'+t.tier+'</div>'+
'<div class="cs2-tourn-name">'+esc(t.name)+'</div>'+
'<div class="cs2-tourn-prize">$'+fmt(t.prize)+'</div>'+
'</div>'+
'<div class="cs2-tourn-meta">'+
esc(t.format.replace(/_/g," ").toUpperCase())+' • '+
esc(t.bo.toUpperCase())+' • '+t.team_count+' teams'+
'</div>'+
'<div class="cs2-tourn-countdown">Starts in '+days_until+' days</div>'+
'</div>';
}).join('') :
'<div class="cs2-empty">No tournaments available right now. Keep playing to unlock higher tiers.</div>';
var detail_html = "";
if(state.selected_tournament){
var t = CS.TOURNAMENTS.find(function(x){ return x.id === state.selected_tournament; });
if(t){
var phases_html = Object.keys(t.phase_days).map(function(ph){
return '<div class="cs2-phase-row">'+
'<span class="cs2-phase-name">'+esc(ph.charAt(0).toUpperCase()+ph.slice(1))+'</span>'+
'<span class="cs2-phase-days">'+t.phase_days[ph]+' day'+(t.phase_days[ph]>1?"s":"")+'</span>'+
'</div>';
}).join('');
var can_enter = P.faceit.lvl >= (t.min_faceit_lvl||1);
detail_html =
'<div class="cs2-tourn-detail">'+
'<div class="cs2-tourn-detail-header">'+
'<div class="cs2-tourn-tier-big cs2-tier-'+t.tier+'">TIER '+t.tier+'</div>'+
'<div class="cs2-tourn-detail-name">'+esc(t.name)+'</div>'+
'<div class="cs2-tourn-detail-prize">Prize Pool: $'+fmt(t.prize)+'</div>'+
'</div>'+
'<div class="cs2-tourn-phases">'+phases_html+'</div>'+
'<div class="cs2-tourn-reqs">'+
'<div class="cs2-req-row'+(P.faceit.lvl>=(t.min_faceit_lvl||1)?' met':'')+'">'+
'<span>FaceIT Level</span><span>'+P.faceit.lvl+' / '+t.min_faceit_lvl+'</span>'+
'</div>'+
'</div>'+
(can_enter?
'<div class="cs2-btn cs2-btn-primary" id="cs2-enter-tourn" data-tourn="'+esc(t.id)+'">ENTER TOURNAMENT</div>':
'<div class="cs2-btn cs2-btn-disabled">Requirements not met</div>'
)+
'</div>';
}
}
var result_html = "";
if(state.last_tournament){
var tr = state.last_tournament;
result_html =
'<div class="cs2-section-title"><span class="cs2-section-bar"></span>LAST TOURNAMENT</div>'+
'<div class="cs2-tourn-result cs2-result-'+(tr.champion?"win":tr.qualified?"win":"loss")+'">'+
'<div class="cs2-tr-name">'+esc(tr.tournament.name)+'</div>'+
'<div class="cs2-tr-outcome">'+(tr.champion?"🏆 Champion":tr.qualified?"✓ Qualified":"Eliminated")+'</div>'+
'<div class="cs2-tr-prize">Prize: $'+fmt(tr.prize_earned||0)+'</div>'+
'</div>';
}
return '<div class="cs2-page">'+
'<div class="cs2-page-head"><div class="cs2-page-title">Tournaments</div><div class="cs2-page-sub">Day '+fmt(day)+'</div></div>'+
result_html+
'<div class="cs2-tourn-layout">'+
'<div class="cs2-tourn-list">'+
'<div class="cs2-section-title"><span class="cs2-section-bar"></span>AVAILABLE</div>'+
list_html+
'</div>'+
'<div class="cs2-tourn-right">'+detail_html+'</div>'+
'</div>'+
'</div>';
}
/* ================================================================
RANKINGS
================================================================ */
function buildRankings(){
var mock_players = [
{ username:"s1mple_god", rating:1.38, kd:1.42, faceit_lvl:10, team:"APX", matches:312, rank:1 },
{ username:"ZywHero", rating:1.31, kd:1.35, faceit_lvl:10, team:"ZNT", matches:289, rank:2 },
{ username:"NiKo_aim", rating:1.28, kd:1.30, faceit_lvl:10, team:"SVR", matches:301, rank:3 },
{ username:"Electronic_x", rating:1.24, kd:1.27, faceit_lvl:10, team:"DYN", matches:275, rank:4 },
{ username:"device_awp", rating:1.20, kd:1.18, faceit_lvl:9, team:"NOV", matches:260, rank:5 },
{ username:"karrigan_igl", rating:1.15, kd:1.10, faceit_lvl:9, team:"VTX", matches:310, rank:6 },
{ username:"ropz_lurk", rating:1.12, kd:1.14, faceit_lvl:9, team:"APX", matches:240, rank:7 },
{ username:"blameF_entry", rating:1.09, kd:1.11, faceit_lvl:8, team:"ECL", matches:220, rank:8 },
{ username:"faze_rain", rating:1.06, kd:1.08, faceit_lvl:8, team:"PHM", matches:198, rank:9 },
{ username:"hunter_aim", rating:1.04, kd:1.05, faceit_lvl:8, team:"AXM", matches:185, rank:10 }
];
var player_rank_est = Math.max(11, 200 - Math.round(P.stats.rating * 50));
var rows = mock_players.map(function(p){
return '<div class="cs2-rank-row">'+
'<div class="cs2-rank-pos">#'+p.rank+'</div>'+
'<div class="cs2-rank-name">'+esc(p.username)+'</div>'+
'<div class="cs2-rank-team">'+esc(p.team)+'</div>'+
'<div class="cs2-fl-badge-sm cs2-fl-'+p.faceit_lvl+'">'+p.faceit_lvl+'</div>'+
'<div class="cs2-rank-stat">'+p.rating+'</div>'+
'<div class="cs2-rank-stat">'+p.kd+'</div>'+
'<div class="cs2-rank-stat muted">'+fmt(p.matches)+'</div>'+
'</div>';
}).join('');
var player_row =
'<div class="cs2-rank-row cs2-rank-row-player">'+
'<div class="cs2-rank-pos">#~'+player_rank_est+'</div>'+
'<div class="cs2-rank-name">'+esc(P.username)+'</div>'+
'<div class="cs2-rank-team">'+(P.career.team_id?CS.getTeam(P.career.team_id).tag:"FREE")+'</div>'+
'<div class="cs2-fl-badge-sm cs2-fl-'+P.faceit.lvl+'">'+P.faceit.lvl+'</div>'+
'<div class="cs2-rank-stat">'+P.stats.rating+'</div>'+
'<div class="cs2-rank-stat">'+P.stats.kd+'</div>'+
'<div class="cs2-rank-stat muted">'+fmt(P.stats.matches_played)+'</div>'+
'</div>';
return '<div class="cs2-page">'+
'<div class="cs2-page-head"><div class="cs2-page-title">Rankings</div><div class="cs2-page-sub">Global leaderboard</div></div>'+
'<div class="cs2-rank-header">'+
'<div class="cs2-rank-pos">Rank</div>'+
'<div class="cs2-rank-name">Player</div>'+
'<div class="cs2-rank-team">Team</div>'+
'<div style="width:28px"></div>'+
'<div class="cs2-rank-stat">Rating</div>'+
'<div class="cs2-rank-stat">K/D</div>'+
'<div class="cs2-rank-stat muted">Matches</div>'+
'</div>'+
'<div class="cs2-rank-list">'+rows+'</div>'+
'<div class="cs2-rank-divider">— Your Position —</div>'+
player_row+
'</div>';
}
/* ================================================================
TEAMS
================================================================ */
function buildTeams(){
var tiers = [1,2,3,4,5];
var sel_team = state.selected_team ? CS.getTeam(state.selected_team) : null;
var list_html = tiers.map(function(tier){
var teams = CS.getTeamsByTier(tier);
return '<div class="cs2-teams-tier-section">'+
'<div class="cs2-teams-tier-label cs2-tier-'+tier+'">TIER '+tier+'</div>'+
teams.map(function(t){
var sel = state.selected_team === t.id;
var is_mine = P.career.team_id === t.id;
return '<div class="cs2-team-card'+(sel?' isActive':'')+(is_mine?' isMine':'')+'" data-team="'+esc(t.id)+'">'+
'<div class="cs2-team-card-tag">'+esc(t.tag)+'</div>'+
'<div class="cs2-team-card-info">'+
'<div class="cs2-team-card-name">'+esc(t.name)+'</div>'+
'<div class="cs2-team-card-sub">'+esc(t.region)+(is_mine?' • <span style="color:rgb(230,87,99)">Your Team</span>':'')+'</div>'+
'</div>'+
'<div class="cs2-team-card-prestige">'+t.prestige+'</div>'+
'</div>';
}).join('')+
'</div>';
}).join('');
var detail_html = sel_team ?
'<div class="cs2-team-detail">'+
'<div class="cs2-team-detail-tag">'+esc(sel_team.tag)+'</div>'+
'<div class="cs2-team-detail-name">'+esc(sel_team.name)+'</div>'+
'<div class="cs2-team-detail-region">'+esc(sel_team.region)+'</div>'+
'<div class="cs2-team-stats-grid">'+
'<div class="cs2-ts-card"><div class="cs2-ts-label">Tier</div><div class="cs2-ts-val">'+sel_team.tier+'</div></div>'+
'<div class="cs2-ts-card"><div class="cs2-ts-label">Prestige</div><div class="cs2-ts-val">'+sel_team.prestige+'</div></div>'+
'<div class="cs2-ts-card"><div class="cs2-ts-label">Fame</div><div class="cs2-ts-val">'+sel_team.fame+'</div></div>'+
'<div class="cs2-ts-card"><div class="cs2-ts-label">Min Salary</div><div class="cs2-ts-val">$'+fmt(sel_team.salary_range[0])+'</div></div>'+
'<div class="cs2-ts-card"><div class="cs2-ts-label">Max Salary</div><div class="cs2-ts-val">$'+fmt(sel_team.salary_range[1])+'</div></div>'+
'<div class="cs2-ts-card"><div class="cs2-ts-label">Roster</div><div class="cs2-ts-val">'+sel_team.roster_size+'v'+sel_team.roster_size+'</div></div>'+
'</div>'+
'<div class="cs2-team-reqs">'+
CS.SCOUT_THRESHOLDS.filter(function(t){ return t.tier === sel_team.tier; }).map(function(t){
return '<div class="cs2-req-row">'+
'<span>Required FaceIT Level</span><span>'+t.min_faceit_lvl+'</span>'+
'</div>'+
'<div class="cs2-req-row">'+
'<span>Required Rating</span><span>'+t.min_rating+'</span>'+
'</div>';
}).join('')+
'</div>'+
'</div>' : '<div class="cs2-empty">Select a team to view details.</div>';
return '<div class="cs2-page">'+
'<div class="cs2-page-head"><div class="cs2-page-title">Teams</div><div class="cs2-page-sub">Browse all organizations</div></div>'+
'<div class="cs2-teams-layout">'+
'<div class="cs2-teams-list">'+list_html+'</div>'+
'<div class="cs2-teams-right">'+detail_html+'</div>'+
'</div>'+
'</div>';
}
/* ================================================================
INBOX
================================================================ */
function buildInbox(){
state.unread = 0;
var msgs = state.messages;
var empty_html = '<div class="cs2-empty">No messages yet. Play matches and tournaments to receive updates.</div>';
var list_html = msgs.length === 0 ? empty_html :
msgs.slice().reverse().map(function(msg, i){
var real_i = msgs.length - 1 - i;
var icon = "✉";
var color = "rgba(255,255,255,.04)";
var border = "rgba(255,255,255,.08)";
if(msg.type==="scout") { icon="🔍"; color="rgba(255,180,50,.05)"; border="rgba(255,180,50,.20)"; }
if(msg.type==="tournament") { icon="🏆"; color="rgba(100,120,255,.05)"; border="rgba(100,120,255,.20)"; }
if(msg.type==="contract") { icon="📋"; color="rgba(230,87,99,.05)"; border="rgba(230,87,99,.20)"; }
if(msg.type==="transfer") { icon="🔄"; color="rgba(100,220,120,.05)"; border="rgba(100,220,120,.20)"; }
if(msg.type==="refrag") { icon="💻"; color="rgba(255,140,40,.05)"; border="rgba(255,140,40,.20)"; }
if(msg.type==="system") { icon="⚙"; color="rgba(255,255,255,.03)"; border="rgba(255,255,255,.10)"; }
if(msg.type==="player") { icon="👤"; color="rgba(200,120,255,.05)"; border="rgba(200,120,255,.18)"; }
if(msg.unread){ border = border.replace(".20",".45").replace(".18",".45").replace(".10",".30"); }
var actions_html = "";
if(msg.type==="scout" && msg.team && !msg.resolved){
actions_html =
'<div class="cs2-msg-actions">'+
'<div class="cs2-btn cs2-btn-primary" data-msgaction="tryout" data-msgidx="'+real_i+'">Accept Tryout</div>'+
'<div class="cs2-btn cs2-btn-secondary" data-msgaction="decline" data-msgidx="'+real_i+'">Decline</div>'+
'</div>';
}
if(msg.type==="transfer" && msg.offer && !msg.resolved){
actions_html =
'<div class="cs2-msg-actions">'+
'<div class="cs2-btn cs2-btn-primary" data-msgaction="accept_transfer" data-msgidx="'+real_i+'">Accept Transfer</div>'+
'<div class="cs2-btn cs2-btn-secondary" data-msgaction="decline" data-msgidx="'+real_i+'">Decline</div>'+
'</div>';
}
if(msg.type==="tournament" && msg.tournament_id && !msg.resolved){
actions_html =
'<div class="cs2-msg-actions">'+
'<div class="cs2-btn cs2-btn-primary" data-msgaction="view_tournament" data-msgidx="'+real_i+'">View Tournament</div>'+
'</div>';
}
return '<div class="cs2-msg-card'+(msg.unread?' unread':'')+(msg.resolved?' resolved':'')+'" style="background:'+color+';border-color:'+border+';">'+
'<div class="cs2-msg-header">'+
'<div class="cs2-msg-icon">'+icon+'</div>'+
'<div class="cs2-msg-meta">'+
'<div class="cs2-msg-from">'+esc(msg.from || "System")+'</div>'+
'<div class="cs2-msg-day">Day '+esc(msg.day || 0)+'</div>'+
'</div>'+
(msg.unread ? '<div class="cs2-msg-dot"></div>' : '')+
'</div>'+
'<div class="cs2-msg-subject">'+esc(msg.subject || "")+'</div>'+
'<div class="cs2-msg-body">'+esc(msg.body || "")+'</div>'+
(msg.resolved ? '<div class="cs2-msg-resolved">'+esc(msg.resolved_text || "Resolved")+'</div>' : '')+
actions_html+
'</div>';
}).join('');
return '<div class="cs2-page">'+
'<div class="cs2-page-head">'+
'<div class="cs2-page-title">Inbox</div>'+
'<div class="cs2-page-sub">'+msgs.length+' message'+(msgs.length!==1?'s':'')+'</div>'+
'</div>'+
'<div class="cs2-inbox-list">'+list_html+'</div>'+
'</div>';
}
/* ================================================================
BIND EVENTS
================================================================ */
function bind(root){
var close_btn = root.querySelector("#cs2-close");
if(close_btn) close_btn.addEventListener("click", function(){ Engine.backward(); });
root.querySelectorAll("[data-tab]").forEach(function(el){
el.addEventListener("click", function(){
state.tab = el.getAttribute("data-tab");
render();
});
});
root.querySelectorAll("[data-goto]").forEach(function(el){
el.addEventListener("click", function(){
state.tab = el.getAttribute("data-goto");
render();
});
});
root.querySelectorAll("[data-mode]").forEach(function(el){
el.addEventListener("click", function(){
state.selected_mode = el.getAttribute("data-mode");
state.selected_skill = null;
render();
});
});
root.querySelectorAll("[data-map]").forEach(function(el){
el.addEventListener("click", function(){
state.selected_map = el.getAttribute("data-map");
root.querySelectorAll("[data-map]").forEach(function(m){ m.classList.remove("isActive"); });
el.classList.add("isActive");
});
});
root.querySelectorAll("[data-skill]").forEach(function(el){
el.addEventListener("click", function(){
state.selected_skill = el.getAttribute("data-skill");
render();
});
});
root.querySelectorAll("[data-spcat]").forEach(function(el){
el.addEventListener("click", function(){
var res = CS.spendSkillPoint(P, el.getAttribute("data-spcat"), el.getAttribute("data-spkey"));
if(res.success){ State.variables.PlayerCS2 = P; render(); }
});
});
/* PLAY BUTTON */
var play_btn = root.querySelector("#cs2-play-btn");
if(play_btn){
play_btn.addEventListener("click", function(){
var mode = state.selected_mode || "faceit";
if(mode === "workshop"){
if(!state.selected_skill) return;
var result = CS.trainSkill(P, state.selected_skill, P.refrag_sub ? 1.5 : 1.0);
var xp_gains = {};
xp_gains[state.selected_skill] = Math.round(result.xp_gained || 10);
var xp_report = CS.gainXP(P, xp_gains);
State.variables.PlayerCS2 = P;
state.post_match = { type:"workshop", xp_report:xp_report, skill:state.selected_skill };
state.tab = "result";
render();
return;
}
var map = state.selected_map || P.map_pool[0] || "de_mirage";
state.match_running = true;
render();
setTimeout(function(){
var match = CS.simulateMatch(P, { map:map, type:mode });
var xp_gains = CS.computeMatchXPGains(P, match);
var xp_report = CS.gainXP(P, xp_gains);
var elo_report = CS.gainELO(P, match.result, match);
var scout = CS.checkScoutOpportunity(P);
/* Scout → inbox */
if(scout){
pushMessage({
type: "scout",
from: scout.team.name,
subject: scout.team.name + " is interested in signing you",
body: "Our scouts have been watching your recent performances. We believe you have what it takes to join " + scout.team.name + " (Tier " + scout.team.tier + ", " + scout.team.region + "). We would like to invite you for a tryout.",
team: scout.team
});
}
/* Fin de contrat */
if(P.career.contract_end && P.career.team_id){
var days_left = P.career.contract_end - (State.variables.Day || 0);
if(days_left <= 30 && days_left > 0 && !state._contract_warned){
state._contract_warned = true;
var warn_team = CS.getTeam(P.career.team_id);
pushMessage({
type: "contract",
from: warn_team ? warn_team.name : "Team",
subject: "Your contract expires in " + days_left + " days",
body: "Your current contract will expire soon. Head to the Career tab to negotiate a renewal or prepare for free agency."
});
}
}
/* Refrag renouvellement */
if(P.refrag_sub && (State.variables.Day || 0) > 0 && (State.variables.Day || 0) % 30 === 0 && !state._refrag_warned){
state._refrag_warned = true;
pushMessage({
type: "refrag",
from: "Refrag.gg",
subject: "Your Refrag subscription renews today",
body: "Your monthly Refrag subscription ($30) has been renewed. You continue to benefit from +" + P.refrag_bonus + "% XP bonus in Workshop mode."
});
}
State.variables.PlayerCS2 = P;
state.match_running = false;
state.last_match = match;
state.post_match = {
type: mode,
match: match,
xp_report: xp_report,
elo_report: elo_report,
scout_notified: !!scout
};
state.tab = "result";
render();
}, 800);
});
}
root.querySelectorAll("[data-tourn]").forEach(function(el){
el.addEventListener("click", function(){
var tid = el.getAttribute("data-tourn");
if(el.id === "cs2-enter-tourn"){
var day = State.variables.Day || 0;
var result = CS.enterTournament(P, tid, day);
State.variables.PlayerCS2 = P;
state.last_tournament = result;
state.selected_tournament = null;
render();
} else {
state.selected_tournament = tid;
render();
}
});
});
root.querySelectorAll("[data-team]").forEach(function(el){
el.addEventListener("click", function(){
state.selected_team = el.getAttribute("data-team");
render();
});
});
root.querySelectorAll("[data-career]").forEach(function(el){
el.addEventListener("click", function(){
var action = el.getAttribute("data-career");
var day = State.variables.Day || 0;
if(action==="negotiate_salary") CS.negotiateContract(P, P.career.current_contract, "salary_increase");
if(action==="negotiate_bench") CS.negotiateContract(P, P.career.current_contract, "no_bench_clause");
if(action==="buyout") CS.leaveTeam(P, "buyout", day);
if(action==="unbench") CS.requestUnbench(P);
if(action==="upgrade_gpu") P.pc.gpu = CS.clamp(P.pc.gpu + 10, 0, 100);
if(action==="upgrade_cpu") P.pc.cpu = CS.clamp(P.pc.cpu + 10, 0, 100);
if(action==="upgrade_hz") P.pc.hz = Math.min(P.pc.hz + 60, 360);
if(action==="buy_refrag"){ P.refrag_sub = true; P.refrag_bonus = 5; }
State.variables.PlayerCS2 = P;
render();
});
});
root.querySelectorAll("[data-choice]").forEach(function(el){
el.addEventListener("click", function(){
var result = CS.resolveChoice(P, el.getAttribute("data-choice"), el.getAttribute("data-option"), null);
State.variables.PlayerCS2 = P;
state.interactive_choice = null;
state.choice_result = result;
render();
});
});
/* INBOX ACTIONS */
root.querySelectorAll("[data-msgaction]").forEach(function(el){
el.addEventListener("click", function(){
var action = el.getAttribute("data-msgaction");
var idx = parseInt(el.getAttribute("data-msgidx"), 10);
var msg = state.messages[idx];
if(!msg) return;
var day = State.variables.Day || 0;
if(action === "decline"){
msg.resolved = true;
msg.resolved_text = "Declined.";
msg.unread = false;
}
if(action === "tryout" && msg.team){
var tryout = CS.runTryout(P, msg.team);
msg.resolved = true;
msg.unread = false;
if(tryout.passed){
var contract = CS.generateContract(P, msg.team);
CS.signContract(P, contract, day);
State.variables.PlayerCS2 = P;
msg.resolved_text = "Tryout passed! Signed with " + msg.team.name + ".";
pushMessage({
type: "contract",
from: msg.team.name,
subject: "Contract signed — " + msg.team.name,
body: "Congratulations! Tryout score: " + tryout.final_score + "/" + tryout.required_score + ". Signed. Salary: $" + contract.salary + "/month for " + contract.duration_days + " days."
});
} else {
msg.resolved_text = "Tryout failed. Score: " + tryout.final_score + "/" + tryout.required_score + ".";
pushMessage({
type: "system",
from: msg.team.name,
subject: "Tryout result — not selected",
body: "You did not pass the tryout (score: " + tryout.final_score + ", required: " + tryout.required_score + "). Keep training and improving your stats."
});
}
}
if(action === "accept_transfer" && msg.offer){
var res = CS.acceptTransferOffer(P, msg.offer, day);
State.variables.PlayerCS2 = P;
msg.resolved = true;
msg.unread = false;
msg.resolved_text = res.message;
}
if(action === "view_tournament" && msg.tournament_id){
state.selected_tournament = msg.tournament_id;
state.tab = "tournaments";
msg.unread = false;
}
render();
});
});
} /* end bind() */
/* INIT */
function init(tries){
var root = document.getElementById("cs2-root");
if(!root){ if(tries>0) requestAnimationFrame(function(){ init(tries-1); }); return; }
if(root.dataset.init==="1") return;
root.dataset.init = "1";
render();
}
init(60);
})();
<</script>><style>
#story{padding:0!important;margin:0!important;}
.cs2-wrap{display:grid;grid-template-columns:220px 1fr;height:100vh;width:100%;background:rgb(6,6,8);overflow:hidden;position:fixed;inset:0;z-index:100;}
.cs2-main{overflow-y:auto;min-height:0;height:100vh;}
.cs2-page{padding:24px 28px;display:flex;flex-direction:column;gap:18px;}
.cs2-page-center{align-items:center;justify-content:center;min-height:400px;}
.cs2-page-head{display:flex;align-items:flex-end;justify-content:space-between;padding-bottom:4px;border-bottom:1px solid rgba(255,255,255,.06);}
.cs2-page-title{font-size:26px;font-weight:950;color:rgba(255,255,255,.95);letter-spacing:.01em;}
.cs2-page-sub{font-size:12px;font-weight:700;color:rgba(255,255,255,.35);letter-spacing:.08em;}
.cs2-sidebar{display:flex;flex-direction:column;gap:0;background:rgba(0,0,0,.5);border-right:1px solid rgba(255,255,255,.06);padding:0;overflow:hidden;}
.cs2-sidebar-brand{padding:18px 18px 6px;font-size:18px;font-weight:950;letter-spacing:.08em;color:rgba(255,255,255,.90);}
.cs2-sidebar-brand span{color:rgb(230,87,99);}
.cs2-close-btn{margin:0 10px 8px;padding:7px 12px;border-radius:7px;background:rgba(255,255,255,.04);border:1px solid rgba(255,255,255,.08);color:rgba(255,255,255,.35);font-size:11px;font-weight:800;letter-spacing:.08em;cursor:pointer;text-align:center;transition:background .12s,color .12s;}
.cs2-close-btn:hover{background:rgba(230,87,99,.10);border-color:rgba(230,87,99,.25);color:rgba(230,87,99,.80);}
.cs2-sidebar-player{display:flex;align-items:center;gap:10px;padding:10px 14px;border-top:1px solid rgba(255,255,255,.05);border-bottom:1px solid rgba(255,255,255,.05);}
.cs2-sidebar-info{display:flex;flex-direction:column;gap:2px;min-width:0;}
.cs2-sidebar-name{font-size:13px;font-weight:900;color:rgba(255,255,255,.90);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
.cs2-sidebar-sub{font-size:10px;font-weight:700;letter-spacing:.10em;color:rgba(255,255,255,.35);}
.cs2-xp-bar-wrap{padding:6px 14px;}
.cs2-xp-bar-label-row{display:flex;align-items:center;justify-content:space-between;margin-bottom:4px;}
.cs2-xp-bar-lbl{font-size:9px;font-weight:900;letter-spacing:.10em;text-transform:uppercase;color:rgba(255,255,255,.30);}
.cs2-elo-val{color:rgba(255,255,255,.55);}
.cs2-sp-alert{font-size:9px;font-weight:950;letter-spacing:.08em;color:rgb(255,180,50);cursor:pointer;padding:1px 6px;border-radius:4px;background:rgba(255,180,50,.10);animation:cs2pulse 1.5s ease-in-out infinite;}
.cs2-xp-bar-track{height:4px;background:rgba(255,255,255,.08);border-radius:999px;overflow:hidden;margin-bottom:4px;}
.cs2-xp-bar-fill{height:100%;background:rgb(230,87,99);border-radius:999px;transition:width .3s;}
.cs2-elo-track{height:3px;background:rgba(255,255,255,.08);border-radius:999px;overflow:hidden;margin-bottom:4px;}
.cs2-elo-fill{height:100%;background:linear-gradient(90deg,rgb(100,200,100),rgb(255,180,50),rgb(200,120,255));border-radius:999px;transition:width .3s;}
.cs2-xp-label{font-size:9px;font-weight:700;color:rgba(255,255,255,.25);letter-spacing:.06em;}
.cs2-nav{display:flex;flex-direction:column;gap:2px;padding:8px 8px;flex:1;overflow-y:auto;}
.cs2-nav-item{display:flex;align-items:center;gap:10px;padding:9px 10px;border-radius:8px;cursor:pointer;user-select:none;transition:background .12s;}
.cs2-nav-item:hover{background:rgba(255,255,255,.05);}
.cs2-nav-item.isActive{background:rgba(230,87,99,.10);border:1px solid rgba(230,87,99,.20);}
.cs2-nav-icon{font-size:14px;width:18px;text-align:center;color:rgba(255,255,255,.50);}
.cs2-nav-label{font-size:12px;font-weight:800;letter-spacing:.06em;color:rgba(255,255,255,.65);flex:1;}
.cs2-nav-item.isActive .cs2-nav-label,.cs2-nav-item.isActive .cs2-nav-icon{color:rgb(230,87,99);}
.cs2-sidebar-footer{padding:10px 14px 14px;border-top:1px solid rgba(255,255,255,.05);display:flex;flex-direction:column;gap:6px;}
.cs2-team-pill{padding:4px 10px;border-radius:6px;background:rgba(230,87,99,.10);border:1px solid rgba(230,87,99,.25);color:rgb(230,87,99);font-size:10px;font-weight:900;letter-spacing:.10em;text-align:center;}
.cs2-team-pill.free{background:rgba(255,255,255,.05);border-color:rgba(255,255,255,.10);color:rgba(255,255,255,.35);}
.cs2-moral-row{display:flex;align-items:center;gap:6px;}
.cs2-moral-label{font-size:9px;font-weight:700;color:rgba(255,255,255,.30);letter-spacing:.08em;width:36px;}
.cs2-moral-track{flex:1;height:3px;background:rgba(255,255,255,.08);border-radius:999px;overflow:hidden;}
.cs2-moral-fill{height:100%;background:rgba(100,220,120,.7);border-radius:999px;}
.cs2-fatigue-fill{height:100%;background:rgba(230,140,50,.7);border-radius:999px;}
.cs2-moral-num{font-size:9px;font-weight:900;color:rgba(255,255,255,.30);width:22px;text-align:right;}
.cs2-fl-badge{width:32px;height:32px;border-radius:8px;display:flex;align-items:center;justify-content:center;font-size:13px;font-weight:950;flex:0 0 auto;}
.cs2-fl-badge-sm{width:24px;height:24px;border-radius:6px;display:flex;align-items:center;justify-content:center;font-size:10px;font-weight:950;flex:0 0 auto;}
.cs2-fl-1,.cs2-fl-2{background:rgba(100,160,100,.15);color:rgb(100,200,100);}
.cs2-fl-3,.cs2-fl-4{background:rgba(255,200,50,.12);color:rgb(255,200,50);}
.cs2-fl-5,.cs2-fl-6{background:rgba(255,140,40,.12);color:rgb(255,140,40);}
.cs2-fl-7,.cs2-fl-8{background:rgba(200,80,80,.15);color:rgb(230,87,99);}
.cs2-fl-9,.cs2-fl-10{background:rgba(180,80,230,.15);color:rgb(200,120,255);}
.cs2-section-title{display:flex;align-items:center;gap:8px;font-size:10px;font-weight:950;letter-spacing:.14em;text-transform:uppercase;color:rgba(255,255,255,.80);}
.cs2-section-bar{width:2px;height:12px;background:rgb(230,87,99);border-radius:999px;flex:0 0 auto;}
.cs2-stat-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:10px;}
.cs2-stat-card{padding:14px 16px;border-radius:10px;background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.07);}
.cs2-stat-val{font-size:22px;font-weight:950;color:rgba(255,255,255,.95);margin-bottom:2px;}
.cs2-stat-label{font-size:11px;font-weight:900;color:rgba(255,255,255,.70);margin-bottom:2px;}
.cs2-stat-sub{font-size:10px;color:rgba(255,255,255,.30);}
.cs2-skills-panel{display:flex;flex-direction:column;gap:8px;padding:14px 16px;background:rgba(255,255,255,.02);border:1px solid rgba(255,255,255,.06);border-radius:12px;}
.cs2-skill-row{display:flex;align-items:center;gap:12px;}
.cs2-skill-name{font-size:11px;font-weight:800;color:rgba(255,255,255,.60);width:80px;letter-spacing:.06em;}
.cs2-skill-bar-wrap{flex:1;height:5px;background:rgba(255,255,255,.08);border-radius:999px;overflow:hidden;}
.cs2-skill-bar-fill{height:100%;background:rgb(230,87,99);border-radius:999px;}
.cs2-skill-val{font-size:11px;font-weight:900;color:rgba(255,255,255,.55);width:28px;text-align:right;}
.cs2-last-match{padding:14px 18px;border-radius:10px;display:flex;align-items:center;gap:18px;border:1px solid rgba(255,255,255,.08);}
.cs2-result-win{border-color:rgba(100,220,120,.25);background:rgba(100,220,120,.05);}
.cs2-result-loss{border-color:rgba(230,87,99,.25);background:rgba(230,87,99,.05);}
.cs2-result-draw{border-color:rgba(255,200,50,.20);background:rgba(255,200,50,.04);}
.cs2-lm-score{font-size:22px;font-weight:950;color:rgba(255,255,255,.95);}
.cs2-lm-meta{font-size:12px;color:rgba(255,255,255,.40);flex:1;}
.cs2-lm-result{font-size:11px;font-weight:950;letter-spacing:.12em;}
.cs2-result-win .cs2-lm-result{color:rgb(100,220,120);}
.cs2-result-loss .cs2-lm-result{color:rgb(230,87,99);}
.cs2-result-draw .cs2-lm-result{color:rgb(255,200,50);}
.cs2-dash-team{display:flex;align-items:center;gap:14px;padding:14px 18px;border-radius:10px;background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.07);}
.cs2-dash-team-tag{width:48px;height:48px;border-radius:10px;background:rgba(230,87,99,.10);border:1px solid rgba(230,87,99,.25);display:flex;align-items:center;justify-content:center;font-size:13px;font-weight:950;color:rgb(230,87,99);}
.cs2-dash-team-name{font-size:16px;font-weight:900;color:rgba(255,255,255,.92);}
.cs2-dash-team-sub{font-size:11px;color:rgba(255,255,255,.40);margin-top:2px;}
.cs2-dash-team-salary{font-size:12px;font-weight:900;color:rgba(100,220,120,.80);margin-top:4px;}
.cs2-dash-freeagent{padding:14px 18px;border-radius:10px;background:rgba(255,255,255,.02);border:1px dashed rgba(255,255,255,.10);color:rgba(255,255,255,.35);font-size:13px;text-align:center;}
.cs2-mode-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:12px;}
.cs2-mode-card{padding:18px 16px;border-radius:12px;background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.07);cursor:pointer;transition:border-color .15s,background .15s;}
.cs2-mode-card.isActive{border-color:rgba(230,87,99,.40);background:rgba(230,87,99,.06);}
.cs2-mode-icon{font-size:22px;margin-bottom:8px;}
.cs2-mode-label{font-size:13px;font-weight:900;color:rgba(255,255,255,.90);margin-bottom:6px;}
.cs2-mode-desc{font-size:11px;color:rgba(255,255,255,.40);line-height:1.5;}
.cs2-map-pool{display:flex;flex-wrap:wrap;gap:8px;}
.cs2-map-chip{padding:6px 14px;border-radius:7px;background:rgba(255,255,255,.05);border:1px solid rgba(255,255,255,.09);font-size:11px;font-weight:800;color:rgba(255,255,255,.65);cursor:pointer;transition:border-color .12s;}
.cs2-map-chip.isActive{border-color:rgba(230,87,99,.45);color:rgb(230,87,99);}
.cs2-skill-select-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:8px;}
.cs2-skill-select-card{padding:12px 10px;border-radius:9px;background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.07);cursor:pointer;text-align:center;transition:border-color .12s;}
.cs2-skill-select-card.isActive{border-color:rgba(230,87,99,.45);background:rgba(230,87,99,.06);}
.cs2-skill-select-name{font-size:11px;font-weight:800;color:rgba(255,255,255,.70);margin-bottom:4px;}
.cs2-skill-select-val{font-size:16px;font-weight:950;color:rgba(255,255,255,.92);}
.cs2-play-actions{display:flex;gap:10px;}
.cs2-btn{display:inline-flex;align-items:center;justify-content:center;padding:10px 24px;border-radius:9px;font-size:12px;font-weight:950;letter-spacing:.10em;cursor:pointer;user-select:none;transition:filter .12s,background .12s;}
.cs2-btn-primary{background:rgba(230,87,99,.14);border:1px solid rgba(230,87,99,.45);color:rgb(230,87,99);}
.cs2-btn-primary:hover{background:rgba(230,87,99,.22);filter:brightness(1.08);}
.cs2-btn-secondary{background:rgba(255,255,255,.05);border:1px solid rgba(255,255,255,.10);color:rgba(255,255,255,.65);}
.cs2-btn-secondary:hover{background:rgba(255,255,255,.09);}
.cs2-btn-danger{background:rgba(230,87,99,.06);border:1px solid rgba(230,87,99,.25);color:rgba(230,87,99,.80);}
.cs2-btn-danger:hover{background:rgba(230,87,99,.12);}
.cs2-btn-disabled{background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.06);color:rgba(255,255,255,.20);cursor:not-allowed;}
.cs2-spinner{width:36px;height:36px;border:3px solid rgba(255,255,255,.08);border-top-color:rgb(230,87,99);border-radius:50%;animation:cs2spin .7s linear infinite;margin-bottom:16px;}
@keyframes cs2spin{to{transform:rotate(360deg);}}
.cs2-running-title{font-size:18px;font-weight:900;color:rgba(255,255,255,.80);}
.cs2-running-sub{font-size:12px;color:rgba(255,255,255,.30);margin-top:4px;}
.cs2-result-banner{padding:20px 24px;border-radius:12px;display:flex;align-items:center;gap:20px;border:1px solid rgba(255,255,255,.08);}
.cs2-rb-score{font-size:32px;font-weight:950;color:rgba(255,255,255,.96);}
.cs2-rb-map{flex:1;font-size:13px;color:rgba(255,255,255,.40);}
.cs2-rb-label{font-size:13px;font-weight:950;letter-spacing:.12em;}
.cs2-result-win .cs2-rb-label{color:rgb(100,220,120);}
.cs2-result-loss .cs2-rb-label{color:rgb(230,87,99);}
.cs2-result-draw .cs2-rb-label{color:rgb(255,200,50);}
.cs2-result-elo-row{display:flex;align-items:center;gap:14px;padding:12px 18px;border-radius:10px;background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.07);}
.cs2-rel-label{font-size:11px;font-weight:950;letter-spacing:.12em;color:rgba(255,255,255,.35);}
.cs2-rel-change{font-size:20px;font-weight:950;}
.cs2-rel-current{font-size:12px;font-weight:700;color:rgba(255,255,255,.45);}
.cs2-levelup-banner{display:flex;align-items:center;gap:14px;padding:16px 20px;border-radius:12px;background:rgba(255,180,50,.06);border:1px solid rgba(255,180,50,.25);}
.cs2-lu-icon{font-size:22px;}
.cs2-lu-text{flex:1;font-size:15px;font-weight:900;color:rgba(255,255,255,.90);}
.cs2-lu-pts{font-size:12px;font-weight:950;color:rgb(255,180,50);padding:4px 10px;border-radius:6px;background:rgba(255,180,50,.10);}
.cs2-xp-breakdown{display:flex;flex-direction:column;gap:6px;padding:14px 16px;background:rgba(255,255,255,.02);border:1px solid rgba(255,255,255,.06);border-radius:12px;}
.cs2-xp-cat-row{display:flex;align-items:center;gap:10px;}
.cs2-xp-cat-name{font-size:11px;font-weight:800;color:rgba(255,255,255,.55);width:90px;}
.cs2-xp-cat-bar-wrap{flex:1;height:4px;background:rgba(255,255,255,.08);border-radius:999px;overflow:hidden;}
.cs2-xp-cat-bar-fill{height:100%;background:rgb(230,87,99);border-radius:999px;}
.cs2-xp-cat-val{font-size:11px;font-weight:900;color:rgba(230,87,99,.80);width:60px;text-align:right;}
.cs2-xp-total-row{font-size:12px;color:rgba(255,255,255,.35);padding:4px 2px;}
.cs2-xp-total-row strong{color:rgba(255,255,255,.70);}
.cs2-match-stats-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:8px;}
.cs2-ms-card{padding:12px 14px;border-radius:9px;background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.06);text-align:center;}
.cs2-ms-val{font-size:20px;font-weight:950;color:rgba(255,255,255,.92);margin-bottom:2px;}
.cs2-ms-label{font-size:10px;font-weight:800;letter-spacing:.10em;text-transform:uppercase;color:rgba(255,255,255,.30);}
.cs2-scout-notif{display:flex;align-items:center;gap:14px;padding:14px 18px;border-radius:10px;background:rgba(255,180,50,.06);border:1px solid rgba(255,180,50,.20);}
.cs2-scout-icon{font-size:20px;}
.cs2-scout-text{flex:1;font-size:13px;color:rgba(255,255,255,.70);}
.cs2-result-actions{display:flex;gap:10px;flex-wrap:wrap;margin-top:4px;}
.cs2-sp-pulse{animation:cs2pulse 1.5s ease-in-out infinite;}
@keyframes cs2pulse{0%,100%{box-shadow:0 0 0 0 rgba(230,87,99,.3);}50%{box-shadow:0 0 0 6px rgba(230,87,99,.0);}}
.cs2-sp-counter{color:rgb(255,180,50);font-weight:950;}
.cs2-sp-hint{font-size:12px;color:rgba(255,255,255,.30);padding:4px 2px;}
.cs2-sp-section{display:flex;flex-direction:column;gap:10px;}
.cs2-sp-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:10px;}
.cs2-sp-card{padding:12px 14px;border-radius:10px;background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.07);display:flex;flex-direction:column;gap:6px;transition:border-color .12s;}
.cs2-sp-card:not(.disabled):hover{border-color:rgba(230,87,99,.25);}
.cs2-sp-card.disabled{opacity:.45;}
.cs2-sp-card-top{display:flex;align-items:center;justify-content:space-between;}
.cs2-sp-name{font-size:10px;font-weight:950;letter-spacing:.10em;text-transform:uppercase;color:rgba(255,255,255,.60);}
.cs2-sp-val{font-size:18px;font-weight:950;color:rgba(255,255,255,.92);}
.cs2-sp-bar-wrap{height:3px;background:rgba(255,255,255,.08);border-radius:999px;overflow:hidden;}
.cs2-sp-bar-fill{height:100%;background:rgb(230,87,99);border-radius:999px;}
.cs2-sp-gain{font-size:10px;color:rgba(255,255,255,.30);}
.cs2-sp-btn{margin-top:4px;}
.cs2-sp-remaining{font-size:12px;font-weight:900;color:rgb(255,180,50);padding:10px 0;align-self:center;}
.cs2-sp-done{font-size:12px;font-weight:900;color:rgba(100,220,120,.70);padding:10px 0;align-self:center;}
.cs2-page-choice{justify-content:center;}
.cs2-choice-context{font-size:11px;font-weight:700;letter-spacing:.10em;text-transform:uppercase;color:rgba(230,87,99,.70);}
.cs2-choice-title{font-size:20px;font-weight:950;color:rgba(255,255,255,.95);max-width:500px;}
.cs2-choice-options{display:flex;flex-direction:column;gap:10px;width:100%;max-width:560px;}
.cs2-choice-card{padding:14px 16px;border-radius:10px;background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.08);cursor:pointer;transition:border-color .12s,background .12s;}
.cs2-choice-card:hover{border-color:rgba(230,87,99,.35);background:rgba(230,87,99,.05);}
.cs2-choice-card-top{display:flex;align-items:center;justify-content:space-between;margin-bottom:6px;}
.cs2-choice-label{font-size:13px;font-weight:900;color:rgba(255,255,255,.92);}
.cs2-choice-skill{font-size:10px;font-weight:800;letter-spacing:.10em;text-transform:uppercase;color:rgb(230,87,99);padding:2px 8px;border-radius:5px;background:rgba(230,87,99,.10);}
.cs2-choice-skill.free{color:rgba(255,255,255,.30);background:rgba(255,255,255,.04);}
.cs2-choice-desc{font-size:12px;color:rgba(255,255,255,.45);margin-bottom:6px;line-height:1.5;}
.cs2-choice-risk{font-size:10px;font-weight:800;color:rgba(230,87,99,.70);letter-spacing:.08em;}
.cs2-choice-risk.safe{color:rgba(100,220,120,.60);}
.cs2-contract-panel{display:flex;flex-direction:column;gap:6px;padding:14px 18px;border-radius:10px;background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.07);}
.cs2-contract-row{display:flex;align-items:center;justify-content:space-between;font-size:13px;color:rgba(255,255,255,.55);}
.cs2-contract-row strong{color:rgba(255,255,255,.88);font-weight:900;}
.cs2-contract-bench{font-size:11px;font-weight:800;color:rgb(230,87,99);padding:6px 10px;border-radius:7px;background:rgba(230,87,99,.08);margin-top:4px;}
.cs2-contract-clause{font-size:11px;font-weight:800;color:rgba(100,220,120,.80);padding:6px 10px;border-radius:7px;background:rgba(100,220,120,.06);margin-top:4px;}
.cs2-career-actions{display:flex;flex-wrap:wrap;gap:8px;}
.cs2-freeagent-panel{padding:20px;border-radius:12px;background:rgba(255,255,255,.02);border:1px dashed rgba(255,255,255,.08);display:flex;flex-direction:column;align-items:center;gap:10px;text-align:center;}
.cs2-freeagent-icon{font-size:28px;opacity:.30;}
.cs2-freeagent-title{font-size:18px;font-weight:950;color:rgba(255,255,255,.80);}
.cs2-freeagent-sub{font-size:13px;color:rgba(255,255,255,.35);}
.cs2-freeagent-requirements{width:100%;display:flex;flex-direction:column;gap:6px;margin-top:6px;}
.cs2-req-row{display:flex;align-items:center;justify-content:space-between;padding:8px 12px;border-radius:8px;background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.06);font-size:12px;font-weight:700;color:rgba(255,255,255,.50);}
.cs2-req-row.met{border-color:rgba(100,220,120,.20);background:rgba(100,220,120,.05);color:rgba(100,220,120,.80);}
.cs2-req-checks{display:flex;gap:10px;}
.cs2-req-checks .ok{color:rgba(100,220,120,.80);}
.cs2-req-checks .nok{color:rgba(230,87,99,.60);}
.cs2-req-tier{font-weight:950;color:rgba(255,255,255,.70);}
.cs2-pc-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:8px;}
.cs2-pc-card{padding:10px 12px;border-radius:9px;background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.07);}
.cs2-pc-label{font-size:9px;font-weight:900;letter-spacing:.12em;text-transform:uppercase;color:rgba(255,255,255,.35);margin-bottom:6px;}
.cs2-pc-bar-wrap{height:4px;background:rgba(255,255,255,.08);border-radius:999px;overflow:hidden;margin-bottom:4px;}
.cs2-pc-bar-fill{height:100%;background:rgb(230,87,99);border-radius:999px;}
.cs2-pc-val{font-size:14px;font-weight:950;color:rgba(255,255,255,.85);}
.cs2-pc-val.large{font-size:18px;}
.cs2-pc-val.bad{color:rgb(230,87,99);}
.cs2-refrag-panel{padding:14px 18px;border-radius:10px;background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.08);display:flex;flex-direction:column;gap:8px;}
.cs2-refrag-panel.active{border-color:rgba(100,220,120,.20);background:rgba(100,220,120,.04);}
.cs2-refrag-status{font-size:13px;font-weight:900;color:rgba(255,255,255,.80);}
.cs2-refrag-desc{font-size:12px;color:rgba(255,255,255,.35);}
.cs2-tourn-layout{display:grid;grid-template-columns:1fr 1fr;gap:18px;}
.cs2-tourn-list{display:flex;flex-direction:column;gap:10px;}
.cs2-tourn-card{padding:14px 16px;border-radius:10px;background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.07);cursor:pointer;transition:border-color .12s;}
.cs2-tourn-card:hover,.cs2-tourn-card.isActive{border-color:rgba(230,87,99,.35);background:rgba(230,87,99,.04);}
.cs2-tourn-card-top{display:flex;align-items:center;gap:10px;margin-bottom:6px;}
.cs2-tourn-tier{padding:2px 8px;border-radius:5px;font-size:10px;font-weight:950;letter-spacing:.10em;}
.cs2-tier-1{background:rgba(200,120,255,.12);color:rgb(200,120,255);}
.cs2-tier-2{background:rgba(230,87,99,.12);color:rgb(230,87,99);}
.cs2-tier-3{background:rgba(255,140,40,.12);color:rgb(255,140,40);}
.cs2-tier-4{background:rgba(255,200,50,.10);color:rgb(255,200,50);}
.cs2-tier-5{background:rgba(255,255,255,.07);color:rgba(255,255,255,.50);}
.cs2-tourn-name{flex:1;font-size:13px;font-weight:900;color:rgba(255,255,255,.90);}
.cs2-tourn-prize{font-size:12px;font-weight:900;color:rgba(100,220,120,.80);}
.cs2-tourn-meta{font-size:11px;color:rgba(255,255,255,.35);margin-bottom:4px;}
.cs2-tourn-countdown{font-size:10px;font-weight:800;color:rgba(255,255,255,.25);}
.cs2-tourn-detail{display:flex;flex-direction:column;gap:12px;padding:16px;border-radius:12px;background:rgba(255,255,255,.02);border:1px solid rgba(255,255,255,.07);}
.cs2-tourn-detail-header{display:flex;flex-direction:column;gap:4px;}
.cs2-tourn-tier-big{display:inline-flex;padding:3px 10px;border-radius:6px;font-size:10px;font-weight:950;letter-spacing:.14em;align-self:flex-start;}
.cs2-tourn-detail-name{font-size:18px;font-weight:950;color:rgba(255,255,255,.95);}
.cs2-tourn-detail-prize{font-size:13px;font-weight:900;color:rgba(100,220,120,.80);}
.cs2-tourn-phases{display:flex;flex-direction:column;gap:4px;}
.cs2-phase-row{display:flex;justify-content:space-between;font-size:12px;color:rgba(255,255,255,.50);padding:5px 0;border-bottom:1px solid rgba(255,255,255,.05);}
.cs2-phase-name{font-weight:800;}
.cs2-phase-days{color:rgba(255,255,255,.30);}
.cs2-tourn-reqs{display:flex;flex-direction:column;gap:6px;}
.cs2-tourn-result{padding:14px 18px;border-radius:10px;display:flex;align-items:center;gap:16px;border:1px solid rgba(255,255,255,.08);}
.cs2-tr-name{font-size:14px;font-weight:900;color:rgba(255,255,255,.80);flex:1;}
.cs2-tr-outcome{font-size:13px;font-weight:950;}
.cs2-result-win .cs2-tr-outcome{color:rgb(100,220,120);}
.cs2-result-loss .cs2-tr-outcome{color:rgb(230,87,99);}
.cs2-tr-prize{font-size:12px;font-weight:900;color:rgba(100,220,120,.70);}
.cs2-rank-header,.cs2-rank-row{display:grid;grid-template-columns:40px 1fr 60px 28px 60px 60px 60px;align-items:center;gap:10px;padding:8px 12px;}
.cs2-rank-header{font-size:9px;font-weight:950;letter-spacing:.12em;text-transform:uppercase;color:rgba(255,255,255,.30);border-bottom:1px solid rgba(255,255,255,.07);}
.cs2-rank-list{display:flex;flex-direction:column;}
.cs2-rank-row{border-radius:8px;font-size:12px;color:rgba(255,255,255,.65);}
.cs2-rank-row:hover{background:rgba(255,255,255,.03);}
.cs2-rank-row-player{background:rgba(230,87,99,.06);border:1px solid rgba(230,87,99,.20);}
.cs2-rank-pos{font-weight:950;color:rgba(255,255,255,.40);font-size:11px;}
.cs2-rank-name{font-weight:800;color:rgba(255,255,255,.85);}
.cs2-rank-team{font-size:10px;font-weight:900;color:rgba(255,255,255,.35);letter-spacing:.08em;}
.cs2-rank-stat{font-weight:900;font-size:12px;text-align:right;}
.cs2-rank-stat.muted{color:rgba(255,255,255,.30);}
.cs2-rank-divider{text-align:center;font-size:10px;color:rgba(255,255,255,.20);padding:10px 0;letter-spacing:.10em;}
.cs2-teams-layout{display:grid;grid-template-columns:1fr 1fr;gap:18px;}
.cs2-teams-list{display:flex;flex-direction:column;gap:14px;overflow-y:auto;}
.cs2-teams-tier-section{display:flex;flex-direction:column;gap:6px;}
.cs2-teams-tier-label{font-size:9px;font-weight:950;letter-spacing:.14em;text-transform:uppercase;padding:3px 8px;border-radius:5px;align-self:flex-start;}
.cs2-team-card{display:flex;align-items:center;gap:12px;padding:10px 14px;border-radius:8px;background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.06);cursor:pointer;transition:border-color .12s;}
.cs2-team-card:hover,.cs2-team-card.isActive{border-color:rgba(230,87,99,.30);}
.cs2-team-card.isMine{border-color:rgba(100,220,120,.20);background:rgba(100,220,120,.03);}
.cs2-team-card-tag{width:38px;height:38px;border-radius:8px;background:rgba(255,255,255,.05);display:flex;align-items:center;justify-content:center;font-size:11px;font-weight:950;color:rgba(255,255,255,.70);flex:0 0 auto;}
.cs2-team-card-info{flex:1;min-width:0;}
.cs2-team-card-name{font-size:13px;font-weight:900;color:rgba(255,255,255,.88);}
.cs2-team-card-sub{font-size:10px;color:rgba(255,255,255,.35);margin-top:2px;}
.cs2-team-card-prestige{font-size:14px;font-weight:950;color:rgba(255,255,255,.35);}
.cs2-teams-right{overflow-y:auto;}
.cs2-team-detail{display:flex;flex-direction:column;gap:12px;padding:16px;border-radius:12px;background:rgba(255,255,255,.02);border:1px solid rgba(255,255,255,.07);}
.cs2-team-detail-tag{font-size:32px;font-weight:950;color:rgba(230,87,99,.90);}
.cs2-team-detail-name{font-size:20px;font-weight:950;color:rgba(255,255,255,.95);}
.cs2-team-detail-region{font-size:11px;font-weight:700;letter-spacing:.12em;text-transform:uppercase;color:rgba(255,255,255,.30);}
.cs2-team-stats-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:8px;}
.cs2-ts-card{padding:10px 12px;border-radius:8px;background:rgba(255,255,255,.03);border:1px solid rgba(255,255,255,.06);}
.cs2-ts-label{font-size:9px;font-weight:900;letter-spacing:.10em;text-transform:uppercase;color:rgba(255,255,255,.30);margin-bottom:4px;}
.cs2-ts-val{font-size:16px;font-weight:950;color:rgba(255,255,255,.88);}
.cs2-team-reqs{display:flex;flex-direction:column;gap:6px;}
.cs2-empty{padding:20px;text-align:center;font-size:13px;color:rgba(255,255,255,.25);}
.cs2-inbox-list{display:flex;flex-direction:column;gap:10px;}
.cs2-msg-card{padding:16px 18px;border-radius:12px;border:1px solid rgba(255,255,255,.08);display:flex;flex-direction:column;gap:8px;transition:border-color .15s;}
.cs2-msg-card.unread{box-shadow:0 0 0 1px rgba(230,87,99,.12);}
.cs2-msg-card.resolved{opacity:.45;}
.cs2-msg-header{display:flex;align-items:center;gap:10px;}
.cs2-msg-icon{font-size:18px;flex:0 0 auto;}
.cs2-msg-meta{flex:1;display:flex;flex-direction:column;gap:2px;}
.cs2-msg-from{font-size:12px;font-weight:900;color:rgba(255,255,255,.80);}
.cs2-msg-day{font-size:10px;color:rgba(255,255,255,.25);font-weight:700;letter-spacing:.08em;}
.cs2-msg-dot{width:8px;height:8px;border-radius:50%;background:rgb(230,87,99);flex:0 0 auto;}
.cs2-msg-subject{font-size:13px;font-weight:900;color:rgba(255,255,255,.92);}
.cs2-msg-body{font-size:12px;color:rgba(255,255,255,.45);line-height:1.6;}
.cs2-msg-resolved{font-size:11px;font-weight:800;color:rgba(100,220,120,.70);padding:5px 10px;border-radius:6px;background:rgba(100,220,120,.06);}
.cs2-msg-actions{display:flex;gap:8px;flex-wrap:wrap;margin-top:4px;}
.cs2-inbox-badge{min-width:18px;height:18px;border-radius:999px;background:rgb(230,87,99);color:#fff;font-size:10px;font-weight:950;display:flex;align-items:center;justify-content:center;padding:0 5px;}
</style>/* =====================================================
*
* ------------------------------------- PATCH TO V2 -------------------------------------
*
*/ ====================================================
<<if $GameVersion.id < 2>>
<<set $GameVersion.id = 2>>
<<set $GameVersion.name = "v.0.B260404">>
// PATCH -----------------------------------------
<<if $Corruption.university >= 5>>
<<set $PsychicPowerMax = 4>>
<<set $PsychicPower = 4>>
<<else>>
<<set $PsychicPowerMax = 3>>
<<set $PsychicPower = 3>>
<</if>>
<<run delete State.variables.Corruption.redlight>>
<<run delete State.variables.Corruption.neighborhood>>
<<run delete State.variables.Corruption.financialquarter>>
<<for _i to 0; _i < $ShopCar.length; _i++>>
<<if $ShopCar[_i].id == "scooter">><<set $ShopCar[_i].price = 1000>><<set $ShopCar[_i].rep = 10>><<set $ShopCar[_i].desc = "+10 Reputation">><</if>>
<<if $ShopCar[_i].id == "car1">><<set $ShopCar[_i].price = 5000>><<set $ShopCar[_i].rep = 50>><<set $ShopCar[_i].desc = "+50 Reputation">><</if>>
<</for>>
<<set $OptSkipMiniGamesOn = false>>
<<set $DealerSellItems = {
1: { "weed": 55 },
2: { "weed": 70 },
3: { "weed": 95 }
}>>
<<if $ShopTrapHouse>>
<<set $ShopTrapHouse.forEach(function(item){ if(item.id === "weed") item.price = 50; })>>
<</if>>
<<script>>
(function(){
var V = State.variables;
var npcs = [
'NPCHousemateFemale','NPCHousemateMale','NPCLandlady','NPCLandlord',
'NPCOnlineFriend','NPCLeftNeighbor','NPCRightNeighbor','NPCBestFriend',
'NPCMate1','NPCMate2','NPCMate3','NPCTeachSport','NPCTeachTech',
'NPCTeachLang','NPCPrincipal','NPCBossGym','NPCBossMarket',
'NPCMayor','NPCHomeless','NPCSexShop'
];
npcs.forEach(function(key){
if(V[key] && V[key].lastCorruptDay === undefined){
V[key].lastCorruptDay = -9;
}
if(V[key] && V[key].lastCorruptBool === undefined){
V[key].lastCorruptBool = false;
}
if(V[key] && V[key].replaytalk === undefined){
V[key].replaytalk = false;
}
});
})();
<</script>>
<<set $PsychicPowerMaxBase = 3>>
// END PATCH -----------------------------------
<</if>>
/* ====================================================
*
* ------------------------------------- PATCH TO V3 -------------------------------------
*
*/ ====================================================
<<if $GameVersion.id < 3>>
<<set $GameVersion.id = 3>>
<<set $GameVersion.name = "v.0.B260710">>
// PATCH -----------------------------------------
<<script>>
(function(){
var V = State.variables;
if(V.ShopMarket && Array.isArray(V.ShopMarket)){
var exists = V.ShopMarket.some(function(item){ return item.id === "alcool"; });
if(!exists){
V.ShopMarket.push({
id: "alcool",
name: "Bottle of alcohol",
price: 15,
img: "assets/img/items/market/alcool.png",
unique: false,
inventory: true,
bought: false,
desc: "An item that can be offered..."
});
}
}
})();
<</script>>
<<set $TalkBestFriendChapter5 = false>>
<<set $ShopSexshop = [
{id:"necklace", name:"Chain necklace", price:30, img:"assets/img/items/sexshop/necklace.webp", unique:true, inventory:true, bought:false, desc:"An item that can be offered..."},
{id:"harness", name:"Body harness", price:30, img:"assets/img/items/sexshop/harness.webp", unique:true, inventory:true, bought:false, desc:"An item that can be offered..."},
]>>
<<set $ShopElectronic = [
{id:"spycam", name:"Hidden Camera", price:300, img:"assets/img/items/electronic/spycam.png", unique:false, inventory:true, bought:false, desc:"Can be placed in locations to discreetly film people without their knowledge."},
]>>
<<set $Spycam = {
bathroom: false,
housematefemale: false,
housematemale: false,
mainbedroom: false,
}>>
<<run delete State.variables.PCLandladyboard>>
<<set $PCMotherboard = {
name: "GIGABYTE H510M H V2",
img: 1,
}>>
<<set $FirstBoughtComponent = false>>
<<set $FirstEditingSpycam = false>>
<<set $PrincipalChapterCurrent5 = false>>
<<set $MakeUniversityClass1 = 0>>
<<set $MakeUniversityClass2 = 0>>
<<set $MakeUniversityClass3 = 0>>
<<set $MakeUniversityClass4 = 0>>
<<set $MakeUniversityClass5 = 0>>
<<set $MakeUniversityClass6 = 0>>
<<set $MayorStoryInfo1 = false>>
<<set $MayorStoryInfo2 = false>>
<<set $MayorStoryInfo3 = false>>
<<set $MayorStoryInfo4 = false>>
<<set $MayorStoryInfo5 = false>>
<<set $MayorStory1DayInt = -9999>>
<<set $MayorStory1InitDayInt = false>>
<<set $MayorStoryEncounter1 = false>>
<<set $MayorStoryEncounter1Goto = false>>
<<set $MayorStoryInfo6 = false>>
<<set $MayorStory2DayInt = -9999>>
<<set $MayorStory2InitDayInt = false>>
<<set $MayorStoryEncounter2 = false>>
<<set $MayorStoryEncounter2Goto = false>>
<<set $MayorStoryInfo7 = false>>
<<set $MayorStoryInfo8 = false>>
<<set $MayorStory3DayInt = -9999>>
<<set $MayorStory3InitDayInt = false>>
<<set $MayorStoryEncounter3 = false>>
<<set $MayorStoryEncounter3Goto = false>>
<<set $MayorStoryInfo9 = false>>
<<set $MayorStoryInfoForSMS = false>>
<<set $MayorStory4DayInt = -9999>>
<<set $MayorStory4InitDayInt = false>>
<<set $MayorStoryInfoSMS1 = false>>
<<set $MayorStoryInfo10 = false>>
<<set $MayorStoryInfo11 = false>>
<<set $MayorStoryInfo12 = false>>
<<set $MayorStory5DayInt = -9999>>
<<set $MayorStory5InitDayInt = false>>
<<set $MayorStoryInfoMail1 = false>>
<<set $MayorStoryInfo13 = false>>
<<set $MayorStory6DayInt = -9999>>
<<set $MayorStory6InitDayInt = false>>
<<set $MayorStoryInfo14 = false>>
<<set $MayorStoryFinish = false>>
/* --- NPCHousemateFemale SMS --- */
<<set $NPCHousemateFemaleSMSTalklvl5DayInt = -9999>>
<<set $NPCHousemateFemaleSMSTalklvl5 = false>>
<<set $NPCHousemateFemaleSMSSend5 = false>>
/* --- NPCLandlady Talk Corruption --- */
<<set $NPCLandladyTalkCorruption1DayInt = -9999>>
<<set $NPCLandladyTalkCorruptionSend1 = false>>
<<set $NPCLandladyCorruptionTalklvl1 = false>>
<<set $NPCLandladyTalkCorruption2DayInt = -9999>>
<<set $NPCLandladyTalkCorruptionSend2 = false>>
<<set $NPCLandladyCorruptionTalklvl2 = false>>
<<set $NPCLandladyTalkCorruption3DayInt = -9999>>
<<set $NPCLandladyTalkCorruptionSend3 = false>>
<<set $NPCLandladyCorruptionTalklvl3 = false>>
<<set $NPCLandladyChapter5 = false>>
<<set $SedativesBought = false>>
<<set $NPCLandladyTalkCorruption5DayInt = -9999>>
<<set $NPCLandladyTalkCorruptionSend5 = false>>
<<set $SedativesDeliveredWaiting = false>>
<<set $LandladyChapter6Story2Played = false>>
<<set $SedativesDelivered = false>>
<<set $LandladyChapter6Story3Played = false>>
<<set $SedativesGlassWater = false>>
<<set $LandladyChapter6Story4Played = false>>
<<set $NPCLandlordSleepDrug = false>>
/* --- NPCBestFriend SMS --- */
<<set $NPCBestFriendSMSTalklvl2DayInt = -9999>>
<<set $NPCBestFriendSMSSend2 = false>>
<<set $NPCBestFriendSMSTalklvl2 = false>>
/* --- NPCPrincipal Mail & SMS --- */
<<set $NPCPrincipalMailTalklvl0DayInt = -9999>>
<<set $UniversitySummonsMail = false>>
<<set $NPCPrincipalMailSend0 = false>>
<<set $NPCPrincipalSMSTalklvl3DayInt = -9999>>
<<set $NPCPrincipalSMSSend3 = false>>
<<set $NPCPrincipalSMSTalklvl3 = false>>
<<set $PrincipalSummonsLvl3 = false>>
<<set $NPCPrincipalSMSTalklvl5DayInt = -9999>>
<<set $NPCPrincipalSMSSend5 = false>>
<<set $NPCPrincipalSMSTalklvl5 = false>>
<<set $NPCPrincipalSMSTalklvl6DayInt = -9999>>
<<set $NPCPrincipalSMSSend6 = false>>
<<set $NPCPrincipalSMSTalklvl6 = false>>
<<set $PrincipalChapter6End = false>>
/* --- NPCMayor SMS --- */
<<set $NPCMayorSMSTalklvl1DayInt = -9999>>
<<set $NPCMayorSMSTalklvl1 = false>>
<<set $NPCMayorSMSTalklvl2DayInt = -9999>>
<<set $NPCMayorSMSTalklvl2 = false>>
<<set $NPCMayorSMSTalklvl5DayInt = -9999>>
<<set $NPCMayorSMSTalklvl5 = false>>
<<set $NPCMayorSMSSend1= false>>
<<set $NPCMayorSMSSend2 = false>>
<<set $NPCMayorSMSSend5 = false>>
/* --- NPCMate3 SMS --- */
<<set $NPCMate3SMSTalklvl5DayInt = -9999>>
<<set $NPCMate3SMSSend5 = false>>
<<set $NPCMate3SMSTalklvl5 = false>>
<<script>>
(function(){
var V = State.variables;
if(!V.MailList) V.MailList = [];
var exists = V.MailList.some(function(m){ return m.id === "MayorStoryInfoMail1"; });
if(!exists){
V.MailList.push({ id:"MayorStoryInfoMail1", title:"Loan Approval Confirmation - Construction Project Financing", pass:"MayorStory21", read:false });
}
})();
<</script>>
<<script>>
(function(){
var V = State.variables;
var imgFix = {
"weed": "assets/img/items/traphouse/weed.webp",
"alcool": "assets/img/items/market/alcool.png",
"medkit": "assets/img/items/hospital/medkit.webp",
"Medkit": "assets/img/items/hospital/medkit.webp",
"spycam": "assets/img/items/electronic/spycam.png",
"camera1": "assets/img/misc/MCPC/camera1.jpg",
"camera2": "assets/img/misc/MCPC/camera2.jpg",
"camera3": "assets/img/misc/MCPC/camera3.jpg",
"cpu2": "assets/img/misc/MCPC/cpu2.jpg",
"cpu3": "assets/img/misc/MCPC/cpu3.jpg",
"gpu2": "assets/img/misc/MCPC/gpu2.webp",
"gpu3": "assets/img/misc/MCPC/gpu3.jpg",
"headset2": "assets/img/misc/MCPC/headset2.jpg",
"headset3": "assets/img/misc/MCPC/headset3.webp",
"keyboard2": "assets/img/misc/MCPC/keyboard2.jpg",
"keyboard3": "assets/img/misc/MCPC/keyboard3.webp",
"microphone1": "assets/img/misc/MCPC/microphone1.jpg",
"microphone2": "assets/img/misc/MCPC/microphone2.jpg",
"microphone3": "assets/img/misc/MCPC/microphone3.jpg",
"Landladyboard2": "assets/img/misc/MCPC/motherboard2.jpg",
"Landladyboard3": "assets/img/misc/MCPC/motherboard3.webp",
"mouse2": "assets/img/misc/MCPC/mouse2.jpg",
"mouse3": "assets/img/misc/MCPC/mouse3.jpg",
"os2": "assets/img/misc/MCPC/os2.png",
"os3": "assets/img/misc/MCPC/os3.png",
"ram2": "assets/img/misc/MCPC/ram2.jpg",
"ram3": "assets/img/misc/MCPC/ram3.webp",
"screen2": "assets/img/misc/MCPC/screen2.jpg",
"screen3": "assets/img/misc/MCPC/screen3.jpg",
"stockage2": "assets/img/misc/MCPC/stockage2.webp",
"stockage3": "assets/img/misc/MCPC/stockage3.webp",
"scooter": "assets/img/items/car/scooter.png",
"car1": "assets/img/items/car/car1.png",
"tshirt1": "assets/img/items/clothing/tshirt1.png",
"pants1": "assets/img/items/clothing/pants1.png",
"shoes1": "assets/img/items/clothing/shoes1.png",
"necklace": "assets/img/items/sexshop/necklace.webp",
"harness": "assets/img/items/sexshop/harness.webp",
"archivefile": "assets/img/items/story/archivefile.webp"
};
var shops = [
V.ShopTrapHouse,
V.ShopMarket,
V.HospitalMarket,
V.ShopElectronic,
V.ShopCar,
V.ShopClothing,
V.ShopSexshop
];
shops.forEach(function(shop){
if(!Array.isArray(shop)) return;
shop.forEach(function(item){
if(item && item.id && imgFix[item.id]){
item.img = imgFix[item.id];
}
});
});
V.Inventory = V.Inventory || {};
Object.keys(imgFix).forEach(function(id){
if(V.Inventory[id] && typeof V.Inventory[id] === 'object'){
V.Inventory[id].img = imgFix[id];
}
});
if(V.Inventory["Medkit"] && !V.Inventory["medkit"]){
V.Inventory["medkit"] = V.Inventory["Medkit"];
delete V.Inventory["Medkit"];
}
})();
<</script>>
<<script>>
var renameMap = {
"Landladyboard2": "Motherboard2",
"Landladyboard3": "Motherboard3"
};
shops.forEach(function(shop){
if(!Array.isArray(shop)) return;
shop.forEach(function(item){
if(item && item.id && renameMap[item.id]){
item.id = renameMap[item.id];
item.name = item.name.replace("Landladyboard", "Motherboard");
}
});
});
Object.keys(renameMap).forEach(function(oldId){
var newId = renameMap[oldId];
if(V.Inventory[oldId]){
V.Inventory[newId] = V.Inventory[oldId];
V.Inventory[newId].id = newId;
V.Inventory[newId].name = V.Inventory[newId].name.replace("Landladyboard", "Motherboard");
delete V.Inventory[oldId];
}
});
<</script>>
<<set $StressPenalty = 0>>
<<set $Story6_4Finish = false>> <<set $Story6_4Current = false>>
<<set $Story6_5Finish = false>> <<set $Story6_5Current = false>>
<<set $Story6_6Finish = false>> <<set $Story6_6Current = false>>
<<set $Story6_7Finish = false>> <<set $Story6_7Current = false>>
<<set $Story6_8Finish = false>> <<set $Story6_8Current = false>>
<<set $Story6_9Finish = false>> <<set $Story6_9Current = false>>
<<set $Story6_10Finish = false>> <<set $Story6_10Current = false>>
<<set $Story6_11Finish = false>> <<set $Story6_11Current = false>>
<<set $Story6_12Finish = false>> <<set $Story6_12Current = false>>
<<set $SpycamStepStory = false>>
<<set $SpycamSoftware = false>>
<<set $DealerSellItems = {
1: { "weed": 55, "coke": 85, "meth": 125 },
2: { "weed": 70, "coke": 115, "meth": 165 },
3: { "weed": 95, "coke": 145, "meth": 205 }
}>>
<<set $IllegalItems = ["weed","coke","meth"]>>
<<set $ShopTrapHouse = [
{id:"weed", name:"10-Pack of Weed", price:50, img:"assets/img/items/traphouse/weed.webp", unique:false, inventory:true, bought:false, desc:"Personally, you don't use it, but other people do..."},
{id:"coke", name:"Gram of Snow", price:75, img:"assets/img/items/traphouse/coke.webp", unique:false, inventory:true, bought:false, desc:"Personally, you don't use it, but other people do..."},
{id:"meth", name:"Bag of Ice", price:110, img:"assets/img/items/traphouse/meth.webp", unique:false, inventory:true, bought:false, desc:"Personally, you don't use it, but other people do..."},
]>>
<<script>>
if(!setup.TalkMedia) setup.TalkMedia = {};
setup.TalkMedia.Landlady = {
lvl0: {
gifs: ["assets/img/character/landlady/lvl0/01.jpg","assets/img/character/landlady/lvl0/02.jpg","assets/img/character/landlady/lvl0/03.jpg"],
texts: ["Yes?","Do you want to talk to me?"]
},
lvl1: {
gifs: ["assets/img/character/landlady/lvl1/01.jpg","assets/img/character/landlady/lvl1/02.jpg","assets/img/character/landlady/lvl1/03.jpg"],
texts: ["Yes?","Do you want to talk to me?"]
},
lvl2: {
gifs: ["assets/img/character/landlady/lvl2/01.jpg","assets/img/character/landlady/lvl2/02.jpg","assets/img/character/landlady/lvl2/03.jpg"],
texts: ["Are you okay?","Did you want to see me?"]
},
lvl3: {
gifs: ["assets/img/character/landlady/lvl3/01.jpg","assets/img/character/landlady/lvl3/02.jpg","assets/img/character/landlady/lvl3/03.jpg","assets/img/character/landlady/lvl3/04.jpg"],
texts: ["Yes, my dear?","Do you need help?"]
},
lvl4: {
gifs: ["assets/img/character/landlady/lvl4/01.jpg","assets/img/character/landlady/lvl4/02.jpg","assets/img/character/landlady/lvl4/03.jpg"],
texts: ["Yes, my master?","How can I help you?"]
},
lvl5: {
gifs: ["assets/img/character/landlady/lvl5/01.jpg","assets/img/character/landlady/lvl5/02.jpg","assets/img/character/landlady/lvl5/03.jpg","assets/img/character/landlady/lvl5/04.jpg","assets/img/character/landlady/lvl5/05.jpg","assets/img/character/landlady/lvl5/06.webp","assets/img/character/landlady/lvl5/07.webp","assets/img/character/landlady/lvl5/08.webp","assets/img/character/landlady/lvl5/09.webp"],
texts: ["Yes, master?","How can I help you?"]
}
};
<</script>>
<<script>>
(function(){
var V = State.variables;
var items = V.ShopElectronic;
var upgrades = {
"Motherboard2": ["PCMotherboard", "MSI MAG B650 Tomahawk WiFi", 2],
"Motherboard3": ["PCMotherboard", "ASUS ROG Crosshair X670E Hero", 3],
"cpu2": ["PCcpu", "AMD Ryzen 5 7600", 2],
"cpu3": ["PCcpu", "AMD Ryzen 9 7950X3D", 3],
"gpu2": ["PCgpu", "NVIDIA GeForce RTX 4070", 2],
"gpu3": ["PCgpu", "ASUS ROG Strix GeForce RTX 4090 OC 24GB", 3],
"ram2": ["PCram", "Corsair Vengeance 32GB (2x16) DDR5-6000 CL36 (EXPO)", 2],
"ram3": ["PCram", "G.SKILL Trident Z5 Neo 64GB (2x32) DDR5-6000 (EXPO)", 3],
"stockage2": ["PCstockage", "WD_BLACK SN770 2TB NVMe", 2],
"stockage3": ["PCstockage", "Samsung 990 PRO 2TB NVMe 2x", 3],
"os2": ["PCos", "Windows 7 Ultimate", 2],
"os3": ["PCos", "Windows 11 Pro", 3],
"screen2": ["PCscreen", "Gigabyte M27Q 27, 2560x1440, 165/170 Hz", 2],
"screen3": ["PCscreen", "LG UltraGear 27GP950-B 27, 4K, 144 Hz, HDMI 2.1", 3],
"keyboard2": ["PCkeyboard", "Logitech K120", 2],
"keyboard3": ["PCkeyboard", "Keychron Q1 Pro", 3],
"mouse2": ["PCmouse", "Logitech G305 LIGHTSPEED", 2],
"mouse3": ["PCmouse", "Razer Viper V3 Pro", 3],
"headset2": ["PCheadset", "HyperX Cloud II", 2],
"headset3": ["PCheadset", "SteelSeries Arctis Nova Pro Wireless", 3],
"microphone1": ["PCmicrophone", "Trust GXT 212 Mico USB", 1],
"microphone2": ["PCmicrophone", "Blue Yeti USB", 2],
"microphone3": ["PCmicrophone", "Shure SM7B + Focusrite Scarlett 2i2 (3rd Gen)", 3],
"camera1": ["PCcamera", "Logitech C270 HD", 1],
"camera2": ["PCcamera", "Logitech C920 HD Pro", 2],
"camera3": ["PCcamera", "Sony ZV-E10 + Sigma 16 mm f/1.4 DC DN", 3],
};
if(!items) return;
items.forEach(function(item){
if(!item.bought) return;
var u = upgrades[item.id];
if(!u) return;
var varName = u[0];
var newName = u[1];
var newImg = u[2];
if(V[varName] && newImg > V[varName].img){
V[varName].name = newName;
V[varName].img = newImg;
V.FirstBoughtComponent = true;
}
});
})();
<</script>>
// END PATCH -----------------------------------
<</if>>
/* ====================================================
*
* ------------------------------------- PATCH TO V4 -------------------------------------
*
*/ ====================================================
/*<<if $GameVersion.id < 4>>
<<set $GameVersion.id = 4>>
<<set $GameVersion.name = "v.0.XXXXXX">>
// PATCH -----------------------------------------
...
// END PATCH -----------------------------------
<</if>>*/
/* ====================================================
*
* --------------------------------- END GOTO RETURN ---------------------------------
*
*/ ====================================================
<<goto $return>><<sound "music" "music.music" true>><<passagebg>><<if $Time !== 3>><<sound "bg" "bg.city" true>><img src="assets/img/misc/city/apartments/apartmentsoutside.webp"/><<else>><<sound "bg" "bg.cityNight" true>><img src="assets/img/misc/city/apartments/apartmentsoutsidenight.webp"/><</if>><</passagebg>>
<<imgcorruption city>>
<div class="BottomUiBarCustom">
<<BottomButton "Move">>[[🏢 Inside|ApartmentsInside]]
[[🏙️ City center|City]]<</BottomButton>>
</div><<sound "music" "music.music" true>><<sound "bg" "bg.empty" true>><<set $InteractInInterior = false>><<passagebg>><<if $Time !== 3>><img src="assets/img/misc/city/apartments/apartmentsinside.webp"/><<else>><img src="assets/img/misc/city/apartments/apartmentsinsidenight.webp"/><</if>><</passagebg>><style>
#appt-panel {
width: 100% !important;
max-width: var(--story-width, 960px) !important;
max-height: 90vh;
display: flex;
flex-direction: column;
overflow: hidden;
justify-self: center;
}
#appt-header{flex:0 0 auto;padding:0 0 18px 0;border-bottom:1px solid rgba(255,255,255,.12);margin-bottom:12px;}
#appt-header-label{font-size:calc(14px + var(--font-boost,0px));font-weight:900;letter-spacing:.20em;text-transform:uppercase;color:rgba(230,87,99,.85);margin-bottom:5px;}
#appt-header-title{font-size:calc(28px + var(--font-boost,0px));font-weight:950;color:rgba(255,255,255,.98);letter-spacing:.01em;line-height:1;}
#appt-list{overflow-y:auto;flex:1 1 auto;display:flex;flex-direction:column;gap:6px;scrollbar-width:none;}
#appt-list::-webkit-scrollbar{display:none;}
.appt-row{display:flex;align-items:center;gap:clamp(8px,2vw,16px);padding:clamp(10px,2vw,14px) clamp(12px,2vw,18px);border-radius:9px;border:1px solid rgba(255,255,255,.12);background:rgba(0,0,0,.45);cursor:pointer;transition:background .12s,border-color .12s;user-select:none;}
.appt-row:hover{background:rgba(0,0,0,.65);border-color:rgba(255,255,255,.22);}
.appt-row-locked{opacity:.45;cursor:default;pointer-events:none;}
.appt-img{width:clamp(36px,5vw,52px);height:clamp(36px,5vw,52px);border-radius:7px;overflow:hidden;flex:0 0 clamp(36px,5vw,52px);border:1px solid rgba(255,255,255,.12);background:rgba(0,0,0,.40);}
.appt-img img{width:100%!important;min-width:0!important;max-width:100%!important;height:100%!important;min-height:0!important;max-height:100%!important;object-fit:cover!important;display:block!important;}
.appt-info{flex:1 1 auto;min-width:0;}
.appt-number{font-size:calc(12px + var(--font-boost,0px));font-weight:900;letter-spacing:.16em;text-transform:uppercase;color:rgba(255,255,255,.55);margin-bottom:4px;}
.appt-name{font-size:calc(16px + var(--font-boost,0px));font-weight:950;color:rgba(255,255,255,.95);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
.appt-badge{flex:0 0 auto;font-size:calc(12px + var(--font-boost,0px));font-weight:950;letter-spacing:.14em;text-transform:uppercase;padding:clamp(5px,1vw,7px) clamp(10px,2vw,16px);border-radius:6px;}
.appt-badge-open{background:rgba(230,87,99,.18);border:1px solid rgba(230,87,99,.55);color:rgb(230,87,99);}
.appt-badge-locked{background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.14);color:rgba(255,255,255,.45);}
</style><div id="appt-panel"><div id="appt-header"><div id="appt-header-label">Building Directory</div><div id="appt-header-title">Apartments</div></div><div id="appt-list"></div></div><<script>>
setTimeout(function(){
var apartments=[
{number:"101",npc:"NPCMate1", accessVar:"NPCMate1ApptAccess", passage:"BedroomMate1"},
{number:"102",npc:"NPCMate2", accessVar:"NPCMate2ApptAccess", passage:"BedroomMate2"},
{number:"203",npc:"NPCMate3", accessVar:"NPCMate3ApptAccess", passage:"BedroomMate3"},
{number:"204",npc:"NPCBestFriend", accessVar:"NPCBestFriendApptAccess", passage:"BedroomBestFriend"},
];
var V=State.variables;
var list=document.getElementById("appt-list");
if(!list)return;
apartments.forEach(function(apt){
var npc=V[apt.npc]||{};
var hasAccess=!!V[apt.accessVar];
var name=npc.name||apt.npc;
var img=npc.img||"";
var row=document.createElement("div");
row.className="appt-row"+(hasAccess?"":" appt-row-locked");
row.innerHTML='<div class="appt-img">'+(img?'<img src="'+img+'" alt="">':'')+'</div><div class="appt-info"><div class="appt-number">Apt. '+apt.number+'</div><div class="appt-name">'+name+'</div></div><div class="appt-badge '+(hasAccess?'appt-badge-open':'appt-badge-locked')+'">'+(hasAccess?'ENTER':'LOCKED')+'</div>';
if(hasAccess){row.addEventListener("click",function(){Engine.play(apt.passage);});}
list.appendChild(row);
});
if(window.applyGlobalFontSize) window.applyGlobalFontSize();
},0);<</script>>
<div class="BottomUiBarCustom">
<<BottomButton "Move">>[[🚪 Outside|ApartmentsOutside]]<</BottomButton>>
</div><<sound "music" "music.music" true>><<sound "bg" "bg.empty" true>><<set $InteractInInterior = true>><<passagebg>><<if $Time !== 3>><img src="assets/img/misc/city/apartments/bedroommate1.webp"/><<else>><img src="assets/img/misc/city/apartments/bedroommate1night.webp"/><</if>><</passagebg>>
<<if $Time == 2>><<Interact $NPCMate1>><<elseif $Time == 3>><<Interact $NPCMate1>><<else>><<InformationUiPopUp "Interact">>There is no one.<</InformationUiPopUp>><</if>>
<div class="BottomUiBarCustom">
<<BottomButton "Move">>[[🚪 Exit|ApartmentsInside]]<</BottomButton>>
</div><<sound "music" "music.music" true>><<sound "bg" "bg.empty" true>><<set $InteractInInterior = true>><<passagebg>><<if $Time !== 3>><img src="assets/img/misc/city/apartments/bedroommate2.webp"/><<else>><img src="assets/img/misc/city/apartments/bedroommate2night.webp"/><</if>><</passagebg>>
<<if $Time == 3>><<Interact $NPCMate2>><<else>><<InformationUiPopUp "Interact">>There is no one.<</InformationUiPopUp>><</if>>
<div class="BottomUiBarCustom">
<<BottomButton "Move">>[[🚪 Exit|ApartmentsInside]]<</BottomButton>>
</div><<sound "music" "music.music" true>><<sound "bg" "bg.empty" true>><<set $InteractInInterior = true>><<passagebg>><<if $Time !== 3>><img src="assets/img/misc/city/apartments/bedroommate3.webp"/><<else>><img src="assets/img/misc/city/apartments/bedroommate3night.webp"/><</if>><</passagebg>>
<<if $Time == 3>><<Interact $NPCMate3>><<else>><<InformationUiPopUp "Interact">>There is no one.<</InformationUiPopUp>><</if>>
<div class="BottomUiBarCustom">
<<BottomButton "Move">>[[🚪 Exit|ApartmentsInside]]<</BottomButton>>
</div><<sound "music" "music.music" true>><<sound "bg" "bg.empty" true>><<set $InteractInInterior = true>><<passagebg>><<if $Time !== 3>><img src="assets/img/misc/city/apartments/bedroombestfriend.webp"/><<else>><img src="assets/img/misc/city/apartments/bedroombestfriendnight.webp"/><</if>><</passagebg>>
<<if $Time == 2>><<Interact $NPCBestFriend>><<elseif $Time == 3>><<Interact $NPCBestFriend>><<else>><<InformationUiPopUp "Interact">>There is no one.<</InformationUiPopUp>><</if>>
<div class="BottomUiBarCustom">
<<BottomButton "Move">>[[🚪 Exit|ApartmentsInside]]<</BottomButton>>
</div><<sound "music" "music.music" true>><<passagebg>><<if $Time !== 3>><<sound "bg" "bg.countryside" true>><img src="assets/img/misc/countryside/countryside.webp"/><<else>><<sound "bg" "bg.countrysideNight" true>><img src="assets/img/misc/countryside/countrysidenight.webp"/><</if>><</passagebg>>
<<imgcorruption countryside>>
<div class="BottomUiBarCustom">
<<BottomButton "Move">>[[🏖️ Beach|Beach]]
[[🌲Forest|Forest]]
<<link "🏙️ City center">><<goto "City">><<set $TravelPerTime++>><</link>><</BottomButton>>
</div><<sound "music" "music.music" true>><<passagebg>><<if $Time !== 3>><<sound "bg" "bg.beach" true>><img src="assets/img/misc/countryside/beach.webp"/><<else>><<sound "bg" "bg.beachNight" true>><img src="assets/img/misc/countryside/beachnight.webp"/><</if>><</passagebg>>
<<imgcorruption beach>>
<div class="BottomUiBarCustom">
<<BottomButton "Move">>[[🏞️ Countryside|Countryside]]<</BottomButton>>
</div><<sound "music" "music.music" true>><<passagebg>><<if $Time !== 3>><<sound "bg" "bg.forest" true>><img src="assets/img/misc/countryside/forest.webp"/><<else>><<sound "bg" "bg.forestNight" true>><img src="assets/img/misc/countryside/forestnight.webp"/><</if>><</passagebg>>
<<imgcorruption forest>>
<div class="BottomUiBarCustom">
<<BottomButton "Move">>[[🏞️ Countryside|Countryside]]<</BottomButton>>
</div><<sound "music" "music.music" true>><<passagebg>><img src="assets/img/misc/MCPC/internet/email/reading.gif"/><</passagebg>><<InformationUiPopUp "Email">><strong>Subject:</strong> Faculty Recruitment - Open Position Announcement
<strong>From:</strong> Office of the Principal
<strong>To:</strong> University Community
Dear members of the university community,
I am pleased to announce that our university is currently seeking a new faculty member to join one of its departments.
As part of our ongoing commitment to academic excellence, we warmly invite all qualified and motivated individuals to apply for this position.
All applications must be submitted through the university's official website. Submissions sent by email or delivered in person will not be considered.
The full job description, eligibility requirements, and application form are all available on the university website. The application deadline is listed on the relevant page.
We strongly encourage anyone meeting the required criteria to take advantage of this opportunity. Every application will be reviewed with the utmost care and attention.
Should you have any questions regarding the application process, please do not hesitate to reach out to the Human Resources department directly.
Sincerely,
<em>Your Principal <<print $NPCPrincipal.name>></em>
<</InformationUiPopUp>>
<div class="BottomUiBarCustom">
<<BottomButton "Story">><<link "➡️ Oh, interesting...">><<set $UniversityJobListing = true>><<goto $MailReturnTo>><<set $MailReturnTo = "">><</link>><</BottomButton>>
</div><<sound "music" "music.music" true>><<passagebg>><img src="assets/img/story/searchwork/search.webp"/><</passagebg>><<InformationUiPopUp "Internet">>I pull up the university's website. After a few clicks, I find my way to the recruitment section, and there it is. A faculty position, newly posted and open to applications.
I take my time reading through the listing. The requirements, the expectations, the department. It all sounds like a real opportunity, the kind I can't afford to pass up.
I start filling out the application form. Name, qualifications, teaching experience, field after field, I make sure every answer counts. Once I'm done, I go back over everything one more time, double-checking for anything I might have missed. Then I attach my resume, and hit submit.
The confirmation page loads. My application has been received.
I close the page. There's nothing left to do now but wait and hope that whoever reads this sees something worth calling back.
<</InformationUiPopUp>>
<div class="BottomUiBarCustom">
<<BottomButton "Story">><<link "➡️ Leave the page">><<goto "Internet">><<set $UniversityHiringDayInt = $Day>><<set $UniversityJobListing = false>><</link>><</BottomButton>>
</div><<sound "music" "music.music" true>><<passagebg>><img src="assets/img/story/searchwork/interviewwork.webp"/><</passagebg>>
<<TalkNPC $NPCPrincipal "Please, come in. Have a seat.">>
<<TalkMC "Thank you for seeing me.">>
<<TalkNPC $NPCPrincipal "Of course. Let's get started. First, could you tell me a little about yourself and your background in education?">>
<<TalkMC "Sure. I have a degree in my field and several years of experience, both in academic settings and in practice. I've always been passionate about teaching and passing on knowledge.">>
<<TalkNPC $NPCPrincipal "Good. And why are you interested in joining our university specifically?">>
<<TalkMC "Your institution has a strong reputation, and I believe my profile fits well with what you're looking for. I'm looking for a stable environment where I can invest myself on the long term.">>
<<TalkNPC $NPCPrincipal "That's a fair answer. How would you describe your teaching approach? What matters most to you when working with students?">>
<<TalkMC "I try to stay accessible and adapt to each student's level. I think it's important to be demanding, but also to know how to listen. A good teacher isn't just someone who knows their subject, it's someone who can make others want to learn.">>
<<InformationUiPopUp "One hour later">><em>After several more questions...</em>
<</InformationUiPopUp>>
<<TalkNPC $NPCPrincipal "Well. I've heard everything I needed to hear. Your profile is solid, and your answers reflect a genuine commitment to the role.">>
<<TalkNPC $NPCPrincipal "I'm pleased to tell you that you've been selected. Welcome to the university.">>
<<TalkMC "Thank you. I won't let you down.">>
<div class="BottomUiBarCustom">
<<BottomButton "Story">><<link "➡️ Exit">><<goto "UniversityPrincipalOffice">><<set $PlayerWorkUniversity = true>><<set $UniversityHiring = false>><</link>><</BottomButton>>
</div><<if $PrincipalChapter6End == false && $Time == 3>><<goto "Talk.Principal.Chapter6">><</if>><<sound "music" "music.music" true>><<sound "bg" "bg.empty" true>><<passagebg>><<if $Time !== 3>><img src="assets/img/misc/neighborhood/principal/home.webp"/><<else>><img src="assets/img/misc/neighborhood/principal/homenight.webp"/><</if>><</passagebg>>
<<if $Time == 3>><<Interact $NPCPrincipal>><<else>><<InformationUiPopUp "Interact">>There is no one.<</InformationUiPopUp>><</if>>
<div class="BottomUiBarCustom">
<<BottomButton "Move">><<link "🚪 Exit">><<set $InteractInInterior = false>><<goto "Neighborhood">><</link>><</BottomButton>>
</div><<sound "music" "music.music" true>><<sound "bg" "bg.empty" true>><<passagebg>><<if $Time !== 3>><img src="assets/img/misc/neighborhood/mayor/home.webp"/><<else>><img src="assets/img/misc/neighborhood/mayor/homenight.webp"/><</if>><</passagebg>>
<<if $Time == 3>><<Interact $NPCMayor>><<else>><<InformationUiPopUp "Interact">>There is no one.<</InformationUiPopUp>><</if>>
<div class="BottomUiBarCustom">
<<BottomButton "Move">><<link "🚪 Exit">><<set $InteractInInterior = false>><<goto "Neighborhood">><</link>><</BottomButton>>
</div><<sound "music" "music.music" true>><<passagebg>><img src="assets/img/misc/MCPC/internet/email/reading.gif"/><</passagebg>><<InformationUiPopUp "Email">><strong>Subject:</strong> Convocation - Meeting with the Principal
<strong>From:</strong> Office of the Principal
<strong>To:</strong> <<print $MCPlayer.firstname>> <<print $MCPlayer.lastname>>
Dear <<print $MCPlayer.firstname>>,
I am writing to request your presence at a meeting in my office at your earliest convenience.
This meeting concerns several matters relating to your academic journey here at the university. I would ask that you come prepared to discuss your experience so far, as I believe a direct conversation will be more productive than any written exchange.
The meeting should not take more than thirty minutes of your time.
I look forward to speaking with you in person.
Sincerely,
<em><<print $NPCPrincipal.name>>, <<print $NPCPrincipal.role>></em>
<</InformationUiPopUp>>
<div class="BottomUiBarCustom">
<<BottomButton "Story">><<link "➡️ Oh, ok...">><<set $UniversitySummons1Finish = true>><<goto $MailReturnTo>><<set $MailReturnTo = "">><</link>><</BottomButton>>
</div><<sound "music" "music.music" true>><<sound "bg" "bg.empty" true>><<passagebg>><img src="assets/img/misc/oldtown/redlight/casino.webp"/><</passagebg>><div class="casino-ui"><div class="casino-title">Casino</div><div class="casino-subtitle">Choose your game</div><div class="casino-grid"><<link "🃏 Pair Match">><<goto "Concentration">><</link>></div></div>
<div class="BottomUiBarCustom"><<BottomButton "Move">>[[🚪 Exit|RedLightDistrict]]<</BottomButton>></div><style>
.casino-ui{
display:flex;
flex-direction:column;
align-items:center;
justify-content:center;
gap:18px;
}
.casino-title{
font-size:clamp(1.6rem,4vw,2.4rem);
font-weight:950;
letter-spacing:.12em;
text-transform:uppercase;
color:rgba(255,200,80,.90);
text-shadow:0 0 30px rgba(255,180,50,.35);
text-align:center;
}
.casino-subtitle{
font-size:clamp(.80rem,2vw,.95rem);
font-weight:800;
letter-spacing:.18em;
text-transform:uppercase;
color:rgba(255,255,255,.35);
margin-bottom:8px;
text-align:center;
}
.casino-grid{
display:flex;
flex-wrap:wrap;
gap:14px;
justify-content:center;
max-width:800px;
padding:0 12px;
}
.casino-grid a{
display:flex;
align-items:center;
justify-content:center;
padding:clamp(12px,2vw,18px) clamp(20px,4vw,36px);
border-radius:12px;
border:1px solid rgba(255,180,50,.35);
background:rgba(255,160,40,.08);
color:rgba(255,200,80,.90);
font-size:clamp(.95rem,2vw,1.15rem);
font-weight:900;
letter-spacing:.10em;
text-transform:uppercase;
text-decoration:none;
cursor:pointer;
transition:background .15s,border-color .15s,transform .12s,box-shadow .15s;
user-select:none;
}
.casino-grid a:hover{
background:rgba(255,160,40,.18);
border-color:rgba(255,200,80,.65);
transform:translateY(-3px);
box-shadow:0 8px 24px rgba(255,160,40,.18);
}
.casino-grid a:active{transform:translateY(-1px);}
</style><<sound "music" "music.music" true>><<sound "bg" "bg.empty" true>><<passagebg>><img src="assets/img/misc/city/park/toilet.webp"/><</passagebg>>
<<imgcorruption toilet>>
<div class="BottomUiBarCustom"><<BottomButton "Action">><<link "🕳️ Glory hole">><<goto "EVENT_GloryHoleParkToilet">><</link>><</BottomButton>>
<<BottomButton "Move">>[[🚪 Exit|Park]]<</BottomButton>>
</div><<sound "music" "music.music" true>><<sound "bg" "bg.empty" true>><<passagebg>><img src="assets/img/misc/city/park/toilet.webp"/><</passagebg>>
<<InformationUiPopUp>>You walk into the public restroom, and looking to the side, you notice there's a hole, looking closer, you can see someone on the other side.<</InformationUiPopUp>>
<img src="assets/img/events/parktoilet/gloryhole.webp"/>
<<TalkMC "Hm... Is someone there?">>
<<TalkRandom "Stranger" "assets/img/character/npc/g6.jpg" "Mmmh?">>
<<TalkRandom "Stranger" "assets/img/character/npc/g6.jpg" "Yeah, you want what exactly? Check the rates right above the hole.">>
<<InformationUiPopUp>>Just above the hole, carved into the public restroom wall, it read:
• Blowjob $50
• Pussy $250
• Anal $500<</InformationUiPopUp>>
<span id="powerChoice"></span><span id="eventChoice"></span>
<div class="BottomUiBarCustom"><span id="action1"><<BottomButton "Action">><<link "🔞 Blowjob">><<if _Power == true>><<set _CanDo = true>><<set _FreeDo = true>><<elseif $Money >= 50>><<set _CanDo = true>><<set _FreeDo = false>><<else>><<set _CanDo = false>><<set _FreeDo = false>><</if>><<if _CanDo>><<if !_FreeDo>><<set $Money -= 50>><</if>><<replace "#eventChoice">>
<<TalkMC "A blowjob">>
<<TalkRandom "Stranger" "assets/img/character/npc/g6.jpg" "Mmmmh, go ahead, put your cock in the hole, I'll take care of that.">>
<<InformationUiPopUp>>Barely after putting your cock through the hole, you feel her mouth wrap around it, her tongue swirling around while moving back and forth.<</InformationUiPopUp>>
<<TalkRandom "Stranger" "assets/img/character/npc/g6.jpg" "<em>Slurp... Glck... Glck... Mmph... Slrp... Glck glck glck...</em>">>
<<set _Blowjob = random(5)>><<if _Blowjob is 0>><img src="assets/img/events/parktoilet/1/1.webp"/><<elseif _Blowjob is 1>><img src="assets/img/events/parktoilet/1/2.webp"/><<elseif _Blowjob is 2>><img src="assets/img/events/parktoilet/1/3.webp"/><<elseif _Blowjob is 3>><img src="assets/img/events/parktoilet/1/4.webp"/><<elseif _Blowjob is 4>><img src="assets/img/events/parktoilet/1/5.webp"/><<elseif _Blowjob is 5>><img src="assets/img/events/parktoilet/1/6.webp"/><</if>>
<<TalkMC "Argh... Here it comes! Arh...">>
<<set _BlowjobEnd = random(1)>><<if _BlowjobEnd is 0>><img src="assets/img/events/parktoilet/1/end/1.webp"/><<elseif _BlowjobEnd is 1>><img src="assets/img/events/parktoilet/1/end/2.webp"/><</if>>
<<TalkRandom "Stranger" "assets/img/character/npc/g6.jpg" "Mmmmh, quite a nice load.">>
<<TalkRandom "Stranger" "assets/img/character/npc/g6.jpg" "Alright, you can go now if you're done...">><</replace>><<replace "#action1">><</replace>><<else>><<replace "#eventChoice">><<InformationUiPopUp "Blowjob" #ff6b6b>><em>You don't have enough money (50$ required).</em><</InformationUiPopUp>><</replace>><</if>><</link>>
<<link "🔞 Pussy">><<if _Power == true>><<set _CanDo = true>><<set _FreeDo = true>><<elseif $Money >= 250>><<set _CanDo = true>><<set _FreeDo = false>><<else>><<set _CanDo = false>><<set _FreeDo = false>><</if>><<if _CanDo>><<if !_FreeDo>><<set $Money -= 250>><</if>><<replace "#eventChoice">>
<<TalkMC "I'll go with the pussy.">>
<<TalkRandom "Stranger" "assets/img/character/npc/g6.jpg" "Perfect, go ahead, put your cock in, you're going to love it.">>
<<TalkRandom "Stranger" "assets/img/character/npc/g6.jpg" "<em>Mmph... Ahh... Hnn... Mmh... Ahh...</em>">>
<<set _Pussy = random(5)>><<if _Pussy is 0>><img src="assets/img/events/parktoilet/2/1.webp"/><<elseif _Pussy is 1>><img src="assets/img/events/parktoilet/2/2.webp"/><<elseif _Pussy is 2>><img src="assets/img/events/parktoilet/2/3.webp"/><<elseif _Pussy is 3>><img src="assets/img/events/parktoilet/2/4.webp"/><<elseif _Pussy is 4>><img src="assets/img/events/parktoilet/2/5.webp"/><<elseif _Pussy is 5>><img src="assets/img/events/parktoilet/2/6.webp"/><<elseif _Pussy is 6>><img src="assets/img/events/parktoilet/2/7.webp"/><<elseif _Pussy is 7>><img src="assets/img/events/parktoilet/2/8.webp"/><</if>>
<<TalkMC "Arh... Here it comes!">>
<<set _PussyEnd = random(1)>><<if _PussyEnd is 0>><img src="assets/img/events/parktoilet/2/end/1.webp"/><<elseif _PussyEnd is 1>><img src="assets/img/events/parktoilet/2/end/2.webp"/><</if>>
<<TalkRandom "Stranger" "assets/img/character/npc/g6.jpg" "Hmmmh... Perfect.">>
<<TalkRandom "Stranger" "assets/img/character/npc/g6.jpg" "Alright, if you're done you can go now...">><</replace>><<replace "#action1">><</replace>><<else>><<replace "#eventChoice">><<InformationUiPopUp "Pussy" #ff6b6b>><em>You don't have enough money (250$ required).</em><</InformationUiPopUp>><</replace>><</if>><</link>>
<<link "🔞 Anal">><<if _Power == true>><<set _CanDo = true>><<set _FreeDo = true>><<elseif $Money >= 500>><<set _CanDo = true>><<set _FreeDo = false>><<else>><<set _CanDo = false>><<set _FreeDo = false>><</if>><<if _CanDo>><<if !_FreeDo>><<set $Money -= 500>><</if>><<replace "#eventChoice">>
<<TalkMC "Going for anal.">>
<<TalkRandom "Stranger" "assets/img/character/npc/g6.jpg" "Whoa, okay, go ahead, put your cock in.">>
<<TalkRandom "Stranger" "assets/img/character/npc/g6.jpg" "<em>Hnng... Ahh... Mmph... Ahh ahh... Hnn...</em>">>
<<set _Anal = random(5)>><<if _Anal is 0>><img src="assets/img/events/parktoilet/3/1.webp"/><<elseif _Anal is 1>><img src="assets/img/events/parktoilet/3/2.webp"/><<elseif _Anal is 2>><img src="assets/img/events/parktoilet/3/3.webp"/><<elseif _Anal is 3>><img src="assets/img/events/parktoilet/3/4.webp"/><<elseif _Anal is 4>><img src="assets/img/events/parktoilet/3/5.webp"/><<elseif _Anal is 5>><img src="assets/img/events/parktoilet/3/6.webp"/><</if>>
<<TalkMC "Argh... Yes, fuck, here it comes!">>
<img src="assets/img/events/parktoilet/3/end/1.webp"/>
<<TalkRandom "Stranger" "assets/img/character/npc/g6.jpg" "Aaaahhhh, incredible.">>
<<TalkRandom "Stranger" "assets/img/character/npc/g6.jpg" "You done? If so you can go now.">><</replace>><<replace "#action1">><</replace>><<else>><<replace "#eventChoice">><<InformationUiPopUp "Anal" #ff6b6b>><em>You don't have enough money (500$ required).</em><</InformationUiPopUp>><</replace>><</if>><</link>><</BottomButton>><span id="action2" style="padding-left: 15px;"><<BottomButton "Decision">><<if $PsychicPower<=0>><<link "🔒 Not enough Psychic Power">><</link>><<else>><<link "🧠 Use power">><<set _Power = true>><<set $PsychicPower -= 1>><<UsePsychicPower>><<replace "#powerChoice">><<InformationUiPopUp "Psychic Power" #7aa2ff>>You decide to use your power to avoid paying.
<em>-1 Psychic Power</em><</InformationUiPopUp>>
<<TalkMC "Now you're going to listen to what I tell you.">>
<<TalkMC "I'll be able to choose what I want, and you're going to do it for free, understood?">>
<<TalkRandom "Stranger" "assets/img/character/npc/g6.jpg" "Uh...">>
<<TalkRandom "Stranger" "assets/img/character/npc/g6.jpg" "... Yes, of course, understood.">><</replace>><<replace "#action2">><</replace>><</link>><</if>><</BottomButton>></span></span><<BottomButton "Move">><<link "↩️ Return">><<goto "ParkToilet">><</link>><</BottomButton>>
</div><<sound "music" "music.music" true>><<sound "bg" "bg.empty" true>><<passagebg>><<if $Time !== 3>><img src="assets/img/misc/university/staffroom.webp"/><<else>><img src="assets/img/misc/university/staffroomnight.webp"/><</if>><</passagebg>><<set _npc = $NPCTeachLang>>
<<InformationUiPopUp>>I walk into the teachers' lounge and spot <<print $NPCTeachLang.name>>, the <<print $NPCTeachLang.role>> professor. I remember that <<print $NPCBestFriend.name>> and I have an assignment to hand in to her.
<</InformationUiPopUp>>
<<TalkMC "Hello, how are you?">>
<<TalkNPC _npc "Mmm?">>
<<TalkNPC _npc "And you are?">>
<<TalkMC "Sorry, I haven't introduced myself. I'm <<print $MCPlayer.firstname>> <<print $MCPlayer.lastname>>, a student at the university and also a support tutor.">>
<<TalkNPC _npc "Oh, I see. Did you want to speak with me?">>
<<TalkMC "Yes, as a student this time. You gave <<print $NPCBestFriend.name>> and me an assignment to hand in. I'd like to talk to you about it.">>
<<TalkNPC _npc "Yes, I remember. How can I help you?">>
<<TalkMC "I wanted to know if it would be possible to have a little more time to finish it.">>
<<TalkNPC _npc "No.">>
<<TalkNPC _npc "If I start making exceptions for certain students, even if you are a support tutor, it's going to generate complaints and it'll never end. So the answer is no.">>
<<InformationUiPopUp>>I expected that. But I wanted to try the normal route before getting to this point. Clearly there's no other option. I'm going to have to nudge fate a little, let's put it that way.
<</InformationUiPopUp>>
<<revealtext "power">><<InformationUiPopUp "Psychic Power" #7aa2ff>>You decide to use your power on <<=_npc.name>>.
<em>-1 Psychic Power</em>
<</InformationUiPopUp>>
<<InformationUiPopUp>>I lower my voice and move closer to her, just enough to stay discreet without drawing attention.
<</InformationUiPopUp>>
<<TalkMC "Listen to me carefully.">>
<<TalkMC "From now on, it doesn't matter whether I hand in the assignment or not, you won't have anything to say about it. You see me as an excellent student, and you will always give me the highest grade, whether I'm working alone or in a group.">>
<<InformationUiPopUp>>I position myself slightly in her line of sight so nobody notices her eyes going blank. A few seconds. Then she comes back.
<</InformationUiPopUp>>
<<TalkNPC _npc "...">>
<<TalkNPC _npc "Well, on reflection... you are an excellent student, it's not a big deal if you don't hand it in. I already know you would have passed it regardless.">>
<<TalkMC "Thank you very much, Professor <<print $NPCTeachLang.name>>.">>
<<TalkNPC _npc "Was that everything?">>
<<TalkMC "Yes, that was everything. Thank you again, goodbye and have a good day.">>
<<TalkNPC _npc "No problem, you too.">><</revealtext>>
<div class="BottomUiBarCustom">
<<BottomButton "Decision">><<revealbtn "power" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>>
<<BottomButton "Move" "moveBtn">><<link "↩️ Return">><<set $TalkBestFriendChapter5 = true>><<set $PsychicPower -= 1>><<goto "UniversityStaffRoom">><</link>><</BottomButton>>
</div><<sound "music" "music.music" true>><<passagebg>><img src="assets/img/story/searchwork/search.webp"/><</passagebg>><<InformationUiPopUp "Internet">>After a few minutes of searching, I come across software compatible with the cameras. The interface is simple and intuitive, and would allow me to link them live to my PC. I could then view the feeds in real time from home, manage multiple cameras simultaneously, and even record footage directly to my hard drive. Exactly what I need.
<</InformationUiPopUp>>
<div class="BottomUiBarCustom">
<<BottomButton "Story">>[[🔍 Look|SpycamSoftware2]]<</BottomButton>>
</div><<sound "music" "music.music" true>><<passagebg>><img src="assets/img/misc/MCPC/internet/email/reading.gif"/><</passagebg>><<InformationUiPopUp "Internet">>After consulting the software's website a bit more, I come across another interesting piece of information, the fact that it allows editing directly within the software, without needing a third-party program. Retouching, cutting, assembling sequences, everything is integrated into a single interface.
I continue browsing the page, reading user reviews, checking out the different available features, then I finally come across the price. <strong>$1000</strong> for the license. It's extremely expensive, but with this I could do everything in one place, without juggling between multiple applications. A significant investment, but one that could be worth it in the long run.
<</InformationUiPopUp>>
<div class="BottomUiBarCustom">
<<BottomButton "Story">><<if $Bank >= 1000>><<link "💳 Buy">><<goto "Internet">><<set $SpycamSoftware = true>><<set $Bank -= 1000>><<Refresh>><</link>><<else>><<link "🔒 <em>You don't have enough money in bank</em>">><</link>><</if>>
<<link "↩️ Leave">><<goto "Internet">><</link>><</BottomButton>>
</div><<script>>
setup.SpycamLabels = {
housematefemale: "Girl Bedroom",
housematemale: "Boy Bedroom"
};
<</script>><<sound "music" "music.music" true>><<if $SpycamUnlocked is undefined>><<set $SpycamUnlocked = {}>><</if>><<if $SpycamMontages is undefined>><<set $SpycamMontages = []>><</if>><<if $SpycamLastUnlockDay is undefined>><<set $SpycamLastUnlockDay = -1>><</if>><<if $SpycamUnlockedToday is undefined>><<set $SpycamUnlockedToday = 0>><</if>><<if $SpycamUploadedCount is undefined>><<set $SpycamUploadedCount = 0>><</if>><<if $SpycamTotalEarned is undefined>><<set $SpycamTotalEarned = 0>><</if>><<set _activeCams = []>><<for _camKey, _camOn range $Spycam>><<if _camOn>><<set _activeCams.push(_camKey)>><</if>><</for>><<set _qualityPC = $PCMotherboard.img + $PCcpu.img + $PCgpu.img + $PCram.img + $PCstockage.img + $PCos.img>><<set _storageLvl = $PCstockage.img>><<set _maxStorage = 5 + Math.max(0, _storageLvl - 1) * 5>><<set _maxStorage = Math.min(15, _maxStorage)>><<if _storageLvl < 1>><<set _maxStorage = 5>><</if>><<set _imageList = []>><<for _ck, _arr range $SpycamUnlocked>><<if $Spycam[_ck]>><<for _idx = 0; _idx < _arr.length; _idx++>><<set _num = _arr[_idx]>><<set _padded = (_num < 10 ? "0" + _num : "" + _num)>><<set _imageList.push({cam:_ck, num:_num, src:"assets/img/spycam/" + _ck + "/" + _padded + ".mp4"})>><</for>><</if>><</for>><<set _totalImages = _imageList.length>><<set _qLabel = "Good">><<set _qClass = "good">><<set _qMod = 0>><<if _qualityPC <= 6>><<set _qLabel = "Mediocre">><<set _qClass = "mediocre">><<set _qMod = -15>><<elseif _qualityPC <= 9>><<set _qLabel = "Correct">><<set _qClass = "correct">><<set _qMod = -5>><<elseif _qualityPC <= 12>><<set _qLabel = "Good">><<set _qClass = "good">><<set _qMod = 0>><<elseif _qualityPC <= 15>><<set _qLabel = "Quality">><<set _qClass = "quality">><<set _qMod = 5>><<else>><<set _qLabel = "Excellent">><<set _qClass = "excellent">><<set _qMod = 10>><</if>><<set _camCounts = {}>><<for _ck, _arr range $SpycamUnlocked>><<if $Spycam[_ck]>><<set _camCounts[_ck] = _arr.length>><</if>><</for>><<nobr>>
<style>
#spyc-app{position:fixed;left:0;right:0;top:var(--spyc-top,0px);bottom:var(--spyc-bottom,0px);display:flex;flex-direction:column;overflow:hidden;z-index:5;background:#0c0e13;color:#edf0f7;font-size:calc(14px + var(--font-boost,0px));font-weight:500;--bg:#0c0e13;--sf:#161921;--sf2:#1e2232;--bd:rgba(255,255,255,.11);--bd2:rgba(255,255,255,.20);--ac:#e65763;--ad:rgba(230,87,99,.16);--tx:#edf0f7;--mu:#9aa5c4;--dm:#6472a0;--gn:#3ecf8e;--gd:rgba(62,207,142,.16);--yw:#f0a500;}
#spyc-app *{box-sizing:border-box;}
#spyc-app ::-webkit-scrollbar{width:4px;height:4px;}
#spyc-app ::-webkit-scrollbar-thumb{background:rgba(255,255,255,.20);border-radius:2px;}
#spyc-app video{display:block;}
.spyc-warn{color:var(--ac) !important;}
.spyc-shell{display:flex;height:100%;overflow:hidden;}
.spyc-main{flex:1;display:flex;flex-direction:column;overflow:hidden;min-width:0;}
.spyc-scroll{flex:1;overflow-y:auto;padding:20px 24px;}
.spyc-pane{display:none;flex-direction:column;flex:1;overflow:hidden;}
.spyc-pane.is-active{display:flex;}
.spyc-sb{width:220px;background:var(--sf);border-right:1px solid var(--bd);display:flex;flex-direction:column;flex-shrink:0;overflow:hidden;}
.spyc-sb-logo{padding:16px;border-bottom:1px solid var(--bd);display:flex;align-items:center;gap:10px;flex-shrink:0;}
.spyc-sb-icon{width:32px;height:32px;background:var(--ac);border-radius:8px;display:flex;align-items:center;justify-content:center;font-size:calc(16px + var(--font-boost,0px));flex-shrink:0;color:#fff;}
.spyc-sb-name{font-size:calc(14px + var(--font-boost,0px));font-weight:700;color:var(--tx);}
.spyc-sb-ver{font-size:calc(14px + var(--font-boost,0px));color:var(--mu);font-weight:500;margin-top:1px;}
.spyc-sb-nav{padding:6px 0;flex:1;overflow-y:auto;}
.spyc-nav-i{display:flex;align-items:center;gap:10px;padding:11px 16px;cursor:pointer;color:var(--mu);transition:all .15s;font-size:calc(14px + var(--font-boost,0px));font-weight:600;border-left:3px solid transparent;user-select:none;}
.spyc-nav-i:hover{background:rgba(255,255,255,.05);color:var(--tx);}
.spyc-nav-i.on{color:var(--tx);background:var(--ad);border-left-color:var(--ac);}
.spyc-nav-i.on .spyc-ni{color:var(--ac);}
.spyc-ni{font-size:calc(15px + var(--font-boost,0px));width:18px;text-align:center;flex-shrink:0;}
.spyc-nbadge{margin-left:auto;background:var(--ac);color:#fff;font-size:calc(12px + var(--font-boost,0px));padding:2px 7px;border-radius:10px;font-weight:700;}
.spyc-sb-cams{border-top:1px solid var(--bd);padding:10px 0 6px;flex-shrink:0;}
.spyc-sec-label{font-size:calc(14px + var(--font-boost,0px));letter-spacing:.08em;text-transform:uppercase;color:var(--dm);padding:0 16px 8px;font-weight:700;}
.spyc-cam-row{display:flex;align-items:center;gap:8px;padding:8px 16px;font-size:calc(14px + var(--font-boost,0px));color:var(--mu);cursor:pointer;transition:background .12s;position:relative;font-weight:500;}
.spyc-cam-row:hover{background:rgba(255,255,255,.04);}
.spyc-cam-row a{position:absolute;inset:0;opacity:0;z-index:2;}
.spyc-cdot{width:7px;height:7px;border-radius:50%;flex-shrink:0;}
.spyc-cdot.rec{background:var(--ac);box-shadow:0 0 6px var(--ac);animation:spycBlink 2.5s ease-in-out infinite;}
.spyc-cdot.on{background:var(--gn);box-shadow:0 0 6px var(--gn);animation:spycBlink 2.5s ease-in-out infinite;}
.spyc-cdot.off{background:var(--dm);}
@keyframes spycBlink{0%,100%{opacity:1;}50%{opacity:.35;}}
.spyc-clabel{flex:1;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;}
.spyc-ccount{color:var(--dm);font-weight:700;}
.spyc-sb-foot{border-top:1px solid var(--bd);padding:12px 16px;flex-shrink:0;}
.spyc-storage-label{font-size:calc(14px + var(--font-boost,0px));font-weight:600;color:var(--mu);display:flex;justify-content:space-between;margin-bottom:8px;}
.spyc-storage-bar{height:4px;background:var(--bd2);border-radius:999px;overflow:hidden;}
.spyc-storage-fill{height:100%;border-radius:999px;background:linear-gradient(90deg,var(--gn) 0%,var(--yw) 60%,var(--ac) 95%);transition:width .3s;}
.spyc-tb{min-height:52px;border-bottom:1px solid var(--bd);display:flex;align-items:center;padding:0 24px;gap:10px;flex-shrink:0;flex-wrap:wrap;}
.spyc-tb-title{font-size:calc(16px + var(--font-boost,0px));font-weight:700;color:var(--tx);}
.spyc-tb-sep{color:var(--dm);margin:0 2px;}
.spyc-tb-sub{font-size:calc(14px + var(--font-boost,0px));color:var(--mu);font-weight:500;}
.spyc-tb-sp{flex:1;min-width:8px;}
.spyc-tb-ind{display:flex;align-items:center;gap:7px;font-size:calc(14px + var(--font-boost,0px));color:var(--mu);font-weight:600;white-space:nowrap;}
.spyc-tb-dot{width:7px;height:7px;border-radius:50%;background:var(--gn);box-shadow:0 0 7px var(--gn);animation:spycBlink 2s ease-in-out infinite;flex-shrink:0;}
.spyc-btn-p{padding:9px 18px;background:var(--ac);color:#fff;border:none;border-radius:8px;font-size:calc(14px + var(--font-boost,0px));font-weight:700;cursor:pointer;transition:all .2s;white-space:nowrap;display:inline-flex;align-items:center;gap:6px;}
.spyc-btn-p:hover{background:#f06573;box-shadow:0 0 18px rgba(230,87,99,.40);}
.spyc-btn-p:disabled{background:var(--sf2);color:var(--dm);cursor:not-allowed;box-shadow:none;}
.spyc-btn-g{padding:9px 18px;border:1px solid var(--bd2);color:var(--mu);background:transparent;border-radius:8px;font-size:calc(14px + var(--font-boost,0px));font-weight:600;cursor:pointer;transition:all .15s;white-space:nowrap;display:inline-flex;align-items:center;gap:6px;}
.spyc-btn-g:hover:not(:disabled){background:var(--sf2);color:var(--tx);}
.spyc-btn-g:disabled{opacity:.4;cursor:default;}
.spyc-vgrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(190px,1fr));gap:12px;}
.spyc-vcard{background:var(--sf);border:1px solid var(--bd);border-radius:10px;overflow:hidden;cursor:pointer;transition:all .2s;position:relative;}
.spyc-vcard:hover{border-color:rgba(230,87,99,.50);transform:translateY(-2px);box-shadow:0 6px 20px rgba(0,0,0,.45);}
.spyc-vcard.sel{border-color:var(--ac);background:rgba(230,87,99,.07);}
.spyc-vthumb{height:120px;position:relative;overflow:hidden;background:var(--sf2);}
.spyc-vthumb video{width:100% !important;height:100% !important;object-fit:cover !important;display:block !important;}
.spyc-vdur{position:absolute;bottom:6px;right:6px;background:rgba(0,0,0,.84);padding:3px 8px;border-radius:4px;font-size:calc(14px + var(--font-boost,0px));color:#fff;font-weight:700;}
.spyc-vcam{position:absolute;top:6px;left:6px;background:rgba(0,0,0,.75);border:1px solid rgba(255,255,255,.14);padding:3px 8px;border-radius:4px;font-size:calc(14px + var(--font-boost,0px));color:var(--mu);font-weight:600;}
.spyc-vinfo{padding:10px 12px;}
.spyc-vname{font-size:calc(14px + var(--font-boost,0px));color:var(--tx);margin-bottom:5px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-weight:600;}
.spyc-vmeta{display:flex;gap:8px;flex-wrap:wrap;}
.spyc-vm{font-size:calc(14px + var(--font-boost,0px));color:var(--mu);font-weight:500;}
.spyc-vcheck{position:absolute;top:6px;right:6px;width:22px;height:22px;border-radius:50%;background:var(--ac);display:flex;align-items:center;justify-content:center;font-size:calc(12px + var(--font-boost,0px));color:#fff;font-weight:700;}
.spyc-editbar{position:sticky;bottom:0;background:linear-gradient(to top,var(--bg) 60%,transparent);padding:16px 0 2px;display:flex;justify-content:flex-end;gap:8px;margin-top:16px;}
.spyc-empty-page{padding:60px 24px;text-align:center;}
.spyc-ei{font-size:calc(40px + var(--font-boost,0px));opacity:.22;display:block;margin-bottom:16px;}
.spyc-et{font-size:calc(18px + var(--font-boost,0px));color:var(--tx);margin-bottom:8px;font-weight:700;}
.spyc-es{font-size:calc(14px + var(--font-boost,0px));color:var(--mu);line-height:1.6;font-weight:500;}
.spyc-elayout{display:flex;flex-direction:column;gap:14px;}
.spyc-pool-box{background:var(--sf);border:1px solid var(--bd);border-radius:10px;padding:16px;}
.spyc-ptitle{font-size:calc(14px + var(--font-boost,0px));letter-spacing:.08em;text-transform:uppercase;color:var(--mu);margin-bottom:12px;font-weight:700;}
.spyc-mg-help{background:var(--sf);border:1px solid var(--bd);border-radius:8px;padding:14px 16px;font-size:calc(14px + var(--font-boost,0px));color:var(--mu);line-height:1.6;display:flex;gap:12px;font-weight:500;}
.spyc-mg-help b{color:var(--tx);font-weight:700;}
.spyc-mg-stat-row{display:flex;gap:8px;flex-wrap:wrap;}
.spyc-mg-stat{background:var(--sf);border:1px solid var(--bd);border-radius:8px;padding:12px 14px;flex:1 1 100px;}
.spyc-mg-stat-lbl{font-size:calc(14px + var(--font-boost,0px));text-transform:uppercase;letter-spacing:.06em;color:var(--mu);font-weight:700;margin-bottom:4px;}
.spyc-mg-stat-val{font-size:calc(20px + var(--font-boost,0px));font-weight:700;color:var(--tx);}
.spyc-mg-stat-val.good{color:var(--gn);}
.spyc-mg-pool-row{display:flex;gap:8px;flex-wrap:wrap;min-height:80px;align-items:flex-start;padding:4px 0;}
.spyc-mg-clip{width:110px;height:72px;border-radius:8px;overflow:hidden;border:1px solid var(--bd2);background:var(--sf2);cursor:grab;position:relative;flex-shrink:0;transition:border-color .15s,transform .12s;}
.spyc-mg-clip:hover{border-color:var(--ac);transform:translateY(-2px);}
.spyc-mg-clip.is-dragging{opacity:.25;}
.spyc-mg-clip video{width:100% !important;height:100% !important;object-fit:cover !important;display:block !important;pointer-events:none;}
.spyc-mg-slot video{pointer-events:none;}
.spyc-mg-clip-num{position:absolute;left:5px;top:5px;width:24px;height:24px;border-radius:5px;background:rgba(0,0,0,.88);color:#fff;font-weight:700;font-size:calc(13px + var(--font-boost,0px));display:flex;align-items:center;justify-content:center;}
.spyc-mg-slots{display:flex;gap:8px;overflow-x:auto;padding:4px 0 6px;}
.spyc-mg-slot{width:110px;height:72px;border-radius:8px;border:1px dashed var(--bd2);background:var(--sf2);flex-shrink:0;display:flex;align-items:center;justify-content:center;color:var(--dm);font-size:calc(14px + var(--font-boost,0px));font-weight:700;position:relative;transition:all .12s;}
.spyc-mg-slot.is-good{border-color:var(--gn);border-style:solid;background:var(--gd);}
.spyc-mg-slot.is-bad{border-color:var(--ac);border-style:solid;background:var(--ad);}
.spyc-mg-slot.is-hover{border-color:var(--ac);border-style:solid;background:var(--ad);transform:scale(1.03);}
.spyc-mg-slot.has-clip{border-style:solid;padding:0;color:transparent;}
.spyc-mg-slot-target{position:absolute;left:5px;top:5px;width:24px;height:24px;border-radius:5px;background:rgba(0,0,0,.88);color:#fff;font-weight:700;font-size:calc(13px + var(--font-boost,0px));display:flex;align-items:center;justify-content:center;z-index:2;}
.spyc-mg-prog-bar{height:4px;background:var(--bd2);border-radius:999px;overflow:hidden;margin-top:4px;}
.spyc-mg-prog-fill{height:100%;border-radius:999px;background:linear-gradient(90deg,#c07070 0%,var(--yw) 50%,var(--gn) 100%);transition:width .25s;}
.spyc-mg-actions{display:flex;gap:8px;flex-wrap:wrap;}
.spyc-tl-box{background:var(--sf);border:1px solid var(--bd);border-radius:10px;padding:16px;display:flex;flex-direction:column;gap:10px;}
.spyc-ulist{display:flex;flex-direction:column;gap:10px;}
.spyc-uitem{background:var(--sf);border:1px solid var(--bd);border-radius:10px;padding:14px 16px;display:flex;align-items:center;gap:14px;flex-wrap:wrap;transition:border-color .14s;}
.spyc-uitem:hover{border-color:var(--bd2);}
.spyc-uthumb{width:76px;height:54px;border-radius:7px;overflow:hidden;flex-shrink:0;background:var(--sf2);border:1px solid var(--bd);}
.spyc-uthumb video{width:100% !important;height:100% !important;object-fit:cover !important;display:block !important;}
.spyc-udetails{flex:1 1 160px;min-width:0;}
.spyc-uname{font-size:calc(14px + var(--font-boost,0px));color:var(--tx);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;margin-bottom:5px;font-weight:600;}
.spyc-umeta{display:flex;gap:8px;flex-wrap:wrap;}
.spyc-um{font-size:calc(14px + var(--font-boost,0px));color:var(--mu);font-weight:500;}
.spyc-um.pos{color:var(--gn);}
.spyc-um.neg{color:var(--ac);}
.spyc-uest{text-align:right;flex-shrink:0;}
.spyc-uest-lbl{font-size:calc(14px + var(--font-boost,0px));text-transform:uppercase;letter-spacing:.06em;color:var(--dm);margin-bottom:4px;font-weight:700;}
.spyc-uest-val{font-size:calc(18px + var(--font-boost,0px));font-weight:700;color:var(--gn);}
.spyc-upload-wrap a{display:inline-flex;align-items:center;padding:9px 18px;border:1px solid var(--ac);color:var(--ac);background:transparent;border-radius:8px;font-size:calc(14px + var(--font-boost,0px));font-weight:600;cursor:pointer;transition:all .15s;text-decoration:none;white-space:nowrap;flex-shrink:0;}
.spyc-upload-wrap a:hover{background:var(--ad);}
.spyc-sgrid{display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:10px;margin-bottom:16px;}
.spyc-scard{background:var(--sf);border:1px solid var(--bd);border-radius:10px;padding:16px;}
.spyc-slabel{font-size:calc(14px + var(--font-boost,0px));letter-spacing:.08em;text-transform:uppercase;color:var(--mu);margin-bottom:10px;font-weight:700;}
.spyc-sval{font-size:calc(26px + var(--font-boost,0px));font-weight:700;color:var(--tx);margin-bottom:4px;line-height:1.1;}
.spyc-schg{font-size:calc(14px + var(--font-boost,0px));color:var(--mu);font-weight:500;}
.spyc-srow2{display:grid;grid-template-columns:1fr 1fr;gap:10px;}
.spyc-gcard{background:var(--sf);border:1px solid var(--bd);border-radius:10px;padding:16px;}
.spyc-gcardtitle{font-size:calc(14px + var(--font-boost,0px));letter-spacing:.08em;text-transform:uppercase;color:var(--mu);margin-bottom:14px;font-weight:700;}
.spyc-ctable{width:100%;border-collapse:collapse;}
.spyc-ctable th{font-size:calc(14px + var(--font-boost,0px));letter-spacing:.06em;text-transform:uppercase;color:var(--dm);text-align:left;padding:0 0 10px;border-bottom:1px solid var(--bd);font-weight:700;}
.spyc-ctable td{padding:10px 0;border-bottom:1px solid var(--bd);color:var(--mu);font-size:calc(14px + var(--font-boost,0px));font-weight:500;vertical-align:middle;}
.spyc-ctable tr:last-child td{border-bottom:none;}
.spyc-cam-st{font-size:calc(14px + var(--font-boost,0px));padding:3px 8px;border-radius:4px;font-weight:700;}
.spyc-cam-st.rec{color:var(--ac);background:var(--ad);border:1px solid rgba(230,87,99,.30);}
.spyc-cam-st.on{color:var(--gn);background:var(--gd);border:1px solid rgba(62,207,142,.30);}
.spyc-cam-st.off{color:var(--dm);background:var(--sf2);border:1px solid var(--bd);}
.spyc-pop{position:absolute;right:16px;bottom:14px;padding:12px 18px;border-radius:9px;background:rgba(62,207,142,.18);border:1px solid rgba(62,207,142,.50);color:var(--gn);font-weight:700;font-size:calc(14px + var(--font-boost,0px));animation:spycPopIn .3s ease,spycPopOut .3s ease 3s forwards;z-index:200;}
.spyc-overlay{position:absolute;inset:0;background:rgba(12,14,19,.90);display:flex;align-items:center;justify-content:center;z-index:100;}
.spyc-modal{background:var(--sf);border:1px solid var(--bd2);border-radius:14px;padding:36px 44px;text-align:center;display:flex;flex-direction:column;align-items:center;gap:14px;max-width:360px;}
.spyc-modal-ic{font-size:calc(28px + var(--font-boost,0px));width:60px;height:60px;border-radius:50%;background:var(--gd);border:1px solid rgba(62,207,142,.40);display:flex;align-items:center;justify-content:center;color:var(--gn);}
.spyc-modal-t{font-size:calc(18px + var(--font-boost,0px));font-weight:700;color:var(--tx);}
.spyc-modal-s{font-size:calc(14px + var(--font-boost,0px));color:var(--mu);line-height:1.6;font-weight:500;}
@keyframes spycPopIn{from{opacity:0;transform:translateX(20px);}to{opacity:1;transform:translateX(0);}}
@keyframes spycPopOut{from{opacity:1;}to{opacity:0;transform:translateY(-10px);}}
@media(max-width:720px){
.spyc-shell{flex-direction:column;}
.spyc-sb{width:100%;height:auto;border-right:none;border-bottom:1px solid var(--bd);flex-direction:row;align-items:stretch;flex-shrink:0;}
.spyc-sb-logo{border-bottom:none;border-right:1px solid var(--bd);padding:10px 12px;flex-shrink:0;}
.spyc-sb-name,.spyc-sb-ver{display:none;}
.spyc-sb-nav{flex-direction:row;padding:0;flex:1;overflow-x:auto;display:flex;align-items:stretch;}
.spyc-nav-i{border-left:none;border-bottom:3px solid transparent;flex-direction:column;gap:3px;align-items:center;justify-content:center;padding:10px 12px;min-width:68px;white-space:nowrap;}
.spyc-nav-i.on{border-left:none;border-bottom-color:var(--ac);background:var(--ad);}
.spyc-ni{font-size:calc(18px + var(--font-boost,0px));width:auto;}
.spyc-nbadge{margin-left:0;margin-top:2px;}
.spyc-sb-cams,.spyc-sb-foot{display:none;}
.spyc-scroll{padding:14px 16px;}
.spyc-tb{padding:0 16px;min-height:48px;}
.spyc-tb-ind{display:none;}
.spyc-srow2{grid-template-columns:1fr;}
.spyc-sgrid{grid-template-columns:repeat(auto-fit,minmax(140px,1fr));}
.spyc-vgrid{grid-template-columns:repeat(auto-fill,minmax(150px,1fr));}
}
@media(max-width:400px){
.spyc-vgrid{grid-template-columns:1fr 1fr;}
.spyc-nav-i{padding:8px 10px;min-width:58px;}
}
</style>
<</nobr>><div id="spyc-app"><div class="spyc-shell"><div class="spyc-sb"><div class="spyc-sb-logo"><div class="spyc-sb-icon">⬡</div><div><div class="spyc-sb-name">SpyView</div><div class="spyc-sb-ver">v2.1 · Day <<print $Day>></div></div></div><nav class="spyc-sb-nav"><div class="spyc-nav-i on" data-pane="footage"><span class="spyc-ni">📁</span>Footage<span class="spyc-nbadge"><<print _totalImages>></span></div><div class="spyc-nav-i" data-pane="editor"><span class="spyc-ni">🎬</span>Editor</div><div class="spyc-nav-i" data-pane="pending"><span class="spyc-ni">📤</span>Pending<span class="spyc-nbadge"><<print $SpycamMontages.length>></span></div><div class="spyc-nav-i" data-pane="stats"><span class="spyc-ni">📊</span>Stats</div></nav><div class="spyc-sb-cams"><div class="spyc-sec-label">Cameras</div><<if _activeCams.length is 0>><div style="padding:5px 16px;font-size:calc(14px + var(--font-boost,0px));color:var(--dm);">None placed</div><<else>><<for _ck range _activeCams>><<set _camName = _ck.charAt(0).toUpperCase() + _ck.slice(1)>><<if setup.SpycamLabels and setup.SpycamLabels[_ck]>><<set _camName = setup.SpycamLabels[_ck]>><</if>><<set _ccount = _camCounts[_ck] || 0>><<capture _ck, _camName, _ccount>><div class="spyc-cam-row" style="position:relative;"><<= '<<link "⠀" "Interact.Spycam">><<set $SpycamCurrentCam to "' + _ck + '">><</link>>'>><span class="spyc-tb-dot"></span><span class="spyc-clabel"><<print _camName>></span><span class="spyc-ccount"><<print _ccount>></span></div><</capture>><</for>><</if>></div><<set _spct = _maxStorage > 0 ? Math.min(100, Math.round((_totalImages / _maxStorage) * 100)) : 0>><div class="spyc-sb-foot"><div class="spyc-storage-label">Storage<span class="<<if _totalImages >= _maxStorage>>spyc-warn<</if>>"><<print _totalImages>>/<<print _maxStorage>></span></div></div></div><div class="spyc-main"><div class="spyc-pane is-active" data-pane="footage"><div class="spyc-tb"><span class="spyc-tb-title">Footage</span><span class="spyc-tb-sep">/</span><span class="spyc-tb-sub"><<print _totalImages>> file<<if _totalImages neq 1>>s<</if>></span><div class="spyc-tb-sp"></div><<if _imageList.length >= 2>><button class="spyc-btn-p" id="spyc-make-btn">🎬 Create Montage <span id="spyc-sel-count">(0)</span></button><<else>><button class="spyc-btn-p" disabled>Need 2+ clips</button><</if>><div class="spyc-tb-ind"><div class="spyc-tb-dot"></div>ONLINE</div></div><div class="spyc-scroll"><<if _imageList.length is 0>><div class="spyc-empty-page"><span class="spyc-ei">📭</span><div class="spyc-et">No Footage Yet</div><div class="spyc-es">Place a spy camera and wait a day.</div></div><<else>><div class="spyc-vgrid" id="spyc-grid"><<for _i = 0; _i < _imageList.length; _i++>><<set _img = _imageList[_i]>><<set _camLbl = _img.cam.charAt(0).toUpperCase() + _img.cam.slice(1)>><<if setup.SpycamLabels and setup.SpycamLabels[_img.cam]>><<set _camLbl = setup.SpycamLabels[_img.cam]>><</if>><<capture _i, _img, _camLbl>><<= '<div class="spyc-vcard" data-idx="'+_i+'" data-cam="'+_img.cam+'"><div class="spyc-vthumb"><video src="'+_img.src+'" muted playsinline preload="metadata"></video><span class="spyc-vcam">'+_camLbl+'</span><span class="spyc-vdur">#'+(_img.num<10?"0"+_img.num:""+_img.num)+'</span></div><div class="spyc-vinfo"><div class="spyc-vname">'+_img.cam+'_'+(_img.num<10?"0"+_img.num:""+_img.num)+'.mp4</div><div class="spyc-vmeta"><span class="spyc-vm">'+_camLbl+'</span></div></div></div>'>><</capture>><</for>></div><div class="spyc-editbar" id="spyc-editbar" style="display:none;"><button class="spyc-btn-g" id="spyc-desel-btn">Deselect all</button><button class="spyc-btn-p" id="spyc-make-btn2">Create Montage (<span id="spyc-sel-count2">0</span>)</button></div><</if>></div></div><div class="spyc-pane" data-pane="editor"><div class="spyc-tb"><span class="spyc-tb-title">Editor</span><span class="spyc-tb-sep">/</span><span class="spyc-tb-sub" id="spyc-ed-sub">No active project</span><div class="spyc-tb-sp"></div><div class="spyc-tb-ind"><div class="spyc-tb-dot"></div>ONLINE</div></div><div class="spyc-scroll" id="spyc-editor-content"><div class="spyc-empty-page"><span class="spyc-ei">🎞️</span><div class="spyc-et">No Active Project</div><div class="spyc-es">Select 2+ clips in Footage, then click "Create Montage".</div></div></div></div><div class="spyc-pane" data-pane="pending"><div class="spyc-tb"><span class="spyc-tb-title">Pending</span><span class="spyc-tb-sep">/</span><span class="spyc-tb-sub"><<print $SpycamMontages.length>> queued</span><div class="spyc-tb-sp"></div><div class="spyc-tb-ind"><div class="spyc-tb-dot"></div>ONLINE</div></div><div class="spyc-scroll"><<if $SpycamMontages.length is 0>><div class="spyc-empty-page"><span class="spyc-ei">📤</span><div class="spyc-et">Nothing to Upload</div><div class="spyc-es">Create a montage to queue it here.</div></div><<else>><div class="spyc-ulist"><<for _mi = 0; _mi < $SpycamMontages.length; _mi++>><<set _m = $SpycamMontages[_mi]>><<set _baseMax = 100 + (_m.imageCount - 2) * 25>><<set _estMin = Math.floor(50 * (1 + (_m.qualityMod + _m.miniBonus) / 100))>><<set _estMax = Math.floor(_baseMax * (1 + (_m.qualityMod + _m.miniBonus) / 100))>><<if _estMin < 0>><<set _estMin = 0>><</if>><<if _estMax < 0>><<set _estMax = 0>><</if>><<capture _mi, _m, _estMin, _estMax>><div class="spyc-uitem"><div class="spyc-uthumb"><<= '<video src="'+_m.thumb+'" muted playsinline preload="metadata"></video>'>></div><div class="spyc-udetails"><div class="spyc-uname"><<print _m.name>>.mp4</div><div class="spyc-umeta"><span class="spyc-um">PC: <<print _m.qualityLabel>></span><<if _m.miniBonus > 0>><span class="spyc-um pos">+<<print _m.miniBonus>>% edit</span><<elseif _m.miniSkipped>><span class="spyc-um">skipped</span><<else>><span class="spyc-um">+0% edit</span><</if>><span class="spyc-um"><<print _m.imageCount>> clips · Day <<print _m.day>></span></div></div><div class="spyc-uest"><div class="spyc-uest-lbl">Est. Sale</div><div class="spyc-uest-val">$<<print _estMin>>–$<<print _estMax>></div></div><span class="spyc-upload-wrap"><<link "⬆ Upload" `passage()`>><<set _q = $SpycamMontages[_mi]>><<set _qBmax = 100 + (_q.imageCount - 2) * 25>><<set _qmod = _q.qualityMod || 0>><<set _bmod = _q.miniBonus || 0>><<set _basePrice = 50 + Math.floor(Math.random() * (_qBmax - 49))>><<set _final = Math.floor(_basePrice * (1 + (_qmod + _bmod) / 100))>><<if _final < 0>><<set _final = 0>><</if>><<set $Bank += _final>><<set $SpycamUploadedCount++>><<set $SpycamTotalEarned += _final>><<set $SpycamMontages.deleteAt(_mi)>><<run setup._SpycamLastSale = _final>><</link>></span></div><</capture>><</for>></div><</if>></div></div><div class="spyc-pane" data-pane="stats"><div class="spyc-tb"><span class="spyc-tb-title">Statistics</span><span class="spyc-tb-sep">/</span><span class="spyc-tb-sub">Overview</span><div class="spyc-tb-sp"></div><div class="spyc-tb-ind"><div class="spyc-tb-dot"></div>ONLINE</div></div><div class="spyc-scroll"><<set _spct2 = _maxStorage > 0 ? Math.min(100, Math.round((_totalImages / _maxStorage) * 100)) : 0>><div class="spyc-sgrid"><div class="spyc-scard"><div class="spyc-slabel">Uploads</div><div class="spyc-sval"><<print $SpycamUploadedCount>></div><div class="spyc-schg">montages sold</div></div><div class="spyc-scard"><div class="spyc-slabel">Revenue</div><div class="spyc-sval">$<<print $SpycamTotalEarned>></div><div class="spyc-schg">total earned</div></div><div class="spyc-scard"><div class="spyc-slabel">Cameras</div><div class="spyc-sval"><<print _activeCams.length>></div><div class="spyc-schg">active online</div></div><div class="spyc-scard"><div class="spyc-slabel">PC Quality</div><div class="spyc-sval"><<print _qLabel>></div><div class="spyc-schg"><<print _qualityPC>>/18 · <<if _qMod >= 0>>+<</if>><<print _qMod>>%</div></div><div class="spyc-scard"><div class="spyc-slabel">Captures</div><div class="spyc-sval"><<print $SpycamUnlockedToday>>/2</div><div class="spyc-schg">today's limit</div></div><div class="spyc-scard"><div class="spyc-slabel">Pending</div><div class="spyc-sval"><<print $SpycamMontages.length>></div><div class="spyc-schg">queued uploads</div></div></div><div class="spyc-srow2"><div class="spyc-gcard"><div class="spyc-gcardtitle">Storage</div><div style="display:flex;justify-content:space-between;align-items:center;font-size:calc(14px + var(--font-boost,0px));color:var(--mu);font-weight:600;margin-bottom:8px;"><span><<print _totalImages>> files</span><span class="<<if _totalImages >= _maxStorage>>spyc-warn<</if>>"><<print _maxStorage>> max</span></div><div class="spyc-gcardtitle">Camera Activity</div><table class="spyc-ctable"><thead><tr><th>Camera</th><th>Status</th><th>Files</th></tr></thead><tbody><<if _activeCams.length is 0>><tr><td colspan="3" style="color:var(--dm);text-align:center;padding:14px 0;font-size:calc(14px + var(--font-boost,0px));">No cameras active</td></tr><<else>><<for _ck range _activeCams>><<set _camName = _ck.charAt(0).toUpperCase() + _ck.slice(1)>><<if setup.SpycamLabels and setup.SpycamLabels[_ck]>><<set _camName = setup.SpycamLabels[_ck]>><</if>><<set _cc2 = _camCounts[_ck] || 0>><<capture _ck, _camName, _cc2>><tr><td><<print _camName>></td><td><span class="spyc-cam-st rec">REC</span></td><td style="color:var(--tx);font-weight:700;"><<print _cc2>></td></tr><</capture>><</for>><</if>></tbody></table></div><div class="spyc-gcard"><div class="spyc-gcardtitle">Revenue History</div><<if $SpycamUploadedCount is 0>><div style="color:var(--dm);font-size:calc(14px + var(--font-boost,0px));padding:24px 0;text-align:center;font-weight:600;">No sales yet</div><<else>><div style="display:flex;flex-direction:column;"><div style="display:flex;justify-content:space-between;align-items:center;padding:12px 0;border-bottom:1px solid var(--bd);"><span style="font-size:calc(14px + var(--font-boost,0px));color:var(--mu);font-weight:500;">Montages sold</span><span style="font-size:calc(18px + var(--font-boost,0px));font-weight:700;color:var(--tx);"><<print $SpycamUploadedCount>></span></div><div style="display:flex;justify-content:space-between;align-items:center;padding:12px 0;border-bottom:1px solid var(--bd);"><span style="font-size:calc(14px + var(--font-boost,0px));color:var(--mu);font-weight:500;">Total revenue</span><span style="font-size:calc(18px + var(--font-boost,0px));font-weight:700;color:var(--gn);">$<<print $SpycamTotalEarned>></span></div><div style="display:flex;justify-content:space-between;align-items:center;padding:12px 0;"><span style="font-size:calc(14px + var(--font-boost,0px));color:var(--mu);font-weight:500;">Avg. per sale</span><span style="font-size:calc(18px + var(--font-boost,0px));font-weight:700;color:var(--tx);">$<<print $SpycamUploadedCount > 0 ? Math.round($SpycamTotalEarned / $SpycamUploadedCount) : 0>></span></div></div><</if>></div></div></div></div></div></div><<if setup._SpycamLastSale>><div class="spyc-pop">💰 Sold for $<<print setup._SpycamLastSale>></div><<run delete setup._SpycamLastSale>><</if>></div>
<<script>>
(function(){
var $ = jQuery;
var V = State.variables;
var selected = [];
var mgState = null;
var currentPassage = passage();
function spycUpdateOffsets(){
var topBar = document.getElementById("ui-bar-top") || document.getElementById("top-ui-bar") || (document.querySelector("#top-ui-bar-inner") && document.querySelector("#top-ui-bar-inner").parentElement);
var botBar = document.getElementById("ui-bar-bottom") || document.getElementById("bottom-ui-bar") || document.querySelector(".BottomUiBar, .BottomUiBarCustom");
var topH = 0, botH = 0;
if(topBar){ topH = topBar.getBoundingClientRect().height; }
if(botBar){ botH = botBar.getBoundingClientRect().height; }
var app = document.getElementById("spyc-app");
if(app){ app.style.setProperty("--spyc-top", topH + "px"); app.style.setProperty("--spyc-bottom", botH + "px"); }
}
spycUpdateOffsets();
setTimeout(spycUpdateOffsets, 50);
setTimeout(spycUpdateOffsets, 200);
window.addEventListener("resize", spycUpdateOffsets);
function spycCleanInvalid(){
if(!V.SpycamUnlocked) V.SpycamUnlocked = {};
if(!setup.SpycamMaxImages) return false;
var changed = false;
for(var ck in V.SpycamUnlocked){
var max = setup.SpycamMaxImages[ck] || 0;
var arr = V.SpycamUnlocked[ck] || [];
var filtered = arr.filter(function(n){ return n >= 1 && n <= max; });
if(filtered.length !== arr.length){ V.SpycamUnlocked[ck] = filtered; changed = true; }
}
return changed;
}
if(setup._SpycamSkipNextUpdate){
delete setup._SpycamSkipNextUpdate;
} else {
var didClean = spycCleanInvalid();
if(didClean){ setup._SpycamSkipNextUpdate = true; Engine.play(currentPassage); return; }
}
function switchPane(pane){
$("#spyc-app .spyc-nav-i").removeClass("on");
$('#spyc-app .spyc-nav-i[data-pane="'+pane+'"]').addClass("on");
$("#spyc-app .spyc-pane").removeClass("is-active");
$('#spyc-app .spyc-pane[data-pane="'+pane+'"]').addClass("is-active");
}
$(document).off("click.spycNav").on("click.spycNav", "#spyc-app .spyc-nav-i", function(){
switchPane($(this).attr("data-pane"));
});
$(document).off("click.spycSel").on("click.spycSel", "#spyc-grid .spyc-vcard", function(){
var idx = parseInt($(this).attr("data-idx"), 10);
var pos = selected.indexOf(idx);
if(pos >= 0){
selected.splice(pos, 1);
$(this).removeClass("sel");
$(this).find(".spyc-vcheck").remove();
} else {
selected.push(idx);
$(this).addClass("sel");
$(this).append('<div class="spyc-vcheck">✓</div>');
}
var n = selected.length;
$("#spyc-sel-count").text("("+n+")");
$("#spyc-sel-count2").text(n);
if(n > 0){ $("#spyc-editbar").show(); } else { $("#spyc-editbar").hide(); }
});
$(document).off("click.spycDesel").on("click.spycDesel", "#spyc-desel-btn", function(){
selected = [];
$("#spyc-grid .spyc-vcard").removeClass("sel").find(".spyc-vcheck").remove();
$("#spyc-sel-count").text("(0)");
$("#spyc-sel-count2").text("0");
$("#spyc-editbar").hide();
});
function buildImageList(){
var list = [];
for(var ck in V.SpycamUnlocked){
if(!V.Spycam[ck]) continue;
var arr = V.SpycamUnlocked[ck] || [];
for(var ai = 0; ai < arr.length; ai++){
var num = arr[ai];
list.push({cam:ck, num:num, src:"assets/img/spycam/"+ck+"/"+(num<10?"0"+num:""+num)+".mp4"});
}
}
return list;
}
var allImages = buildImageList();
function muteAllVideos(){
document.querySelectorAll('#spyc-app video').forEach(function(v){
v.muted = true;
v.defaultMuted = true;
v.volume = 0;
});
}
setTimeout(muteAllVideos, 100);
function makeMutedVideo(src, styles){
var v = document.createElement('video');
v.muted = true;
v.defaultMuted = true;
v.volume = 0;
v.preload = 'metadata';
v.setAttribute('playsinline','');
v.addEventListener('play', function(){ this.pause(); this.muted = true; this.volume = 0; });
v.addEventListener('playing', function(){ this.pause(); this.muted = true; this.volume = 0; });
v.addEventListener('volumechange', function(){ if(!this.muted){ this.muted = true; this.volume = 0; } });
if(styles) v.style.cssText = styles;
v.src = src;
return v;
}
function triggerMake(){
if(selected.length < 2){
try{ Wikifier.wikifyEval('<<InformationUiPopUp "Select at least 2 clips">>'); }catch(e){}
return;
}
var imageList = buildImageList();
var picked = selected.map(function(i){ return imageList[i]; }).filter(Boolean);
if(picked.length < 2) return;
if(V.OptSkipMiniGamesOn){ finalizeMontage(picked, 0, true); return; }
startMiniGame(picked);
}
$(document).off("click.spycMake").on("click.spycMake", "#spyc-make-btn, #spyc-make-btn2", triggerMake);
function startMiniGame(picked){
mgState = {
picked: picked,
clips: picked.map(function(p, i){ return { id: i, src: p.src, cam: p.cam, num: p.num, currentSlot: -1 }; }),
slotOrder: null
};
var ord = mgState.clips.map(function(c){ return c.id; });
for(var s = ord.length - 1; s > 0; s--){
var j = Math.floor(Math.random() * (s + 1));
var t = ord[s]; ord[s] = ord[j]; ord[j] = t;
}
mgState.slotOrder = ord;
switchPane("editor");
$("#spyc-ed-sub").text(picked.length + " clips selected");
var html =
'<div class="spyc-elayout">' +
'<div class="spyc-mg-help"><span style="font-size:calc(18px + var(--font-boost,0px));flex-shrink:0;">💡</span><div><b>How to edit:</b> Each clip has a number. Drag it onto the matching numbered slot. Slots turn <span style="color:var(--gn)">green</span> when correct. Full accuracy gives <b>+15% sale bonus</b>.</div></div>' +
'<div class="spyc-mg-stat-row">' +
'<div class="spyc-mg-stat"><div class="spyc-mg-stat-lbl">Clips</div><div class="spyc-mg-stat-val" id="spyc-mg-clips">0</div></div>' +
'<div class="spyc-mg-stat"><div class="spyc-mg-stat-lbl">Placed</div><div class="spyc-mg-stat-val" id="spyc-mg-placed">0</div></div>' +
'<div class="spyc-mg-stat"><div class="spyc-mg-stat-lbl">Correct</div><div class="spyc-mg-stat-val good" id="spyc-mg-correct">0</div></div>' +
'<div class="spyc-mg-stat"><div class="spyc-mg-stat-lbl">Bonus</div><div class="spyc-mg-stat-val good" id="spyc-mg-bonus">+0%</div></div>' +
'</div>' +
'<div class="spyc-pool-box"><div class="spyc-ptitle">Clip pool - drag onto the timeline</div><div class="spyc-mg-pool-row" id="spyc-mg-pool"></div></div>' +
'<div class="spyc-tl-box"><div class="spyc-ptitle">Timeline - drop clips into matching numbered slots</div><div class="spyc-mg-slots" id="spyc-mg-slots"></div><div class="spyc-mg-prog-bar"><div class="spyc-mg-prog-fill" id="spyc-mg-prog-fill" style="width:0%;"></div></div></div>' +
'<div class="spyc-mg-actions"><button class="spyc-btn-p" id="spyc-mg-finish">✓ Finish & Render</button><button class="spyc-btn-g" id="spyc-mg-skip">⏭ Skip editing</button></div>' +
'</div>';
$("#spyc-editor-content").html(html);
renderMG();
muteAllVideos();
}
function renderMG(){
if(!mgState) return;
var $pool = $("#spyc-mg-pool");
var $slots = $("#spyc-mg-slots");
$pool.empty();
var anyLeft = false;
mgState.clips.forEach(function(c){
if(c.currentSlot >= 0) return;
anyLeft = true;
var $clip = $('<div class="spyc-mg-clip" draggable="true" data-id="'+c.id+'"><span class="spyc-mg-clip-num">'+(c.id+1)+'</span></div>');
$clip.append(makeMutedVideo(c.src, 'width:100%;height:100%;object-fit:cover;display:block;border-radius:8px;'));
$pool.append($clip);
});
if(!anyLeft){ $pool.html('<div style="color:var(--gn);padding:14px;font-size:calc(14px + var(--font-boost,0px));font-weight:700;">✓ All clips placed on the timeline.</div>'); }
$slots.empty();
mgState.slotOrder.forEach(function(targetId, slotIdx){
var $slot = $('<div class="spyc-mg-slot" data-slot="'+slotIdx+'" data-target="'+targetId+'"><span class="spyc-mg-slot-target">'+(targetId+1)+'</span></div>');
var clipHere = mgState.clips.find(function(c){ return c.currentSlot === slotIdx; });
if(clipHere){
$slot.addClass("has-clip");
$slot.attr("draggable", "true");
if(clipHere.id === targetId) $slot.addClass("is-good"); else $slot.addClass("is-bad");
$slot.append(makeMutedVideo(clipHere.src, 'position:absolute;inset:0;width:100%;height:100%;object-fit:cover;border-radius:7px;pointer-events:none;'));
$slot.attr("data-clip", clipHere.id);
}
$slots.append($slot);
});
var placed = mgState.clips.filter(function(c){ return c.currentSlot >= 0; }).length;
var correct = mgState.clips.filter(function(c){ if(c.currentSlot < 0) return false; return mgState.slotOrder[c.currentSlot] === c.id; }).length;
var total = mgState.clips.length;
var bonus = total > 0 ? Math.round((correct / total) * 15) : 0;
var pct = total > 0 ? Math.round((correct / total) * 100) : 0;
$("#spyc-mg-clips").text(total);
$("#spyc-mg-placed").text(placed + "/" + total);
$("#spyc-mg-correct").text(correct + "/" + total);
$("#spyc-mg-bonus").text("+" + bonus + "%");
$("#spyc-mg-prog-fill").css("width", pct + "%");
muteAllVideos();
}
$(document).off("dragstart.spycMG").on("dragstart.spycMG", ".spyc-mg-clip, .spyc-mg-slot.has-clip", function(e){
var id = $(this).attr("data-id") || $(this).attr("data-clip");
e.originalEvent.dataTransfer.setData("text/plain", id);
$(this).addClass("is-dragging");
});
$(document).off("dragend.spycMG").on("dragend.spycMG", ".spyc-mg-clip, .spyc-mg-slot", function(){ $(this).removeClass("is-dragging"); });
$(document).off("dragover.spycMG").on("dragover.spycMG", ".spyc-mg-slot", function(e){ e.preventDefault(); $(this).addClass("is-hover"); });
$(document).off("dragleave.spycMG").on("dragleave.spycMG", ".spyc-mg-slot", function(){ $(this).removeClass("is-hover"); });
$(document).off("drop.spycMG").on("drop.spycMG", ".spyc-mg-slot", function(e){
e.preventDefault();
$(this).removeClass("is-hover");
if(!mgState) return;
var clipId = parseInt(e.originalEvent.dataTransfer.getData("text/plain"), 10);
var targetSlotIdx = parseInt($(this).attr("data-slot"), 10);
if(isNaN(clipId) || isNaN(targetSlotIdx)) return;
var existing = mgState.clips.find(function(c){ return c.currentSlot === targetSlotIdx; });
var moving = mgState.clips.find(function(c){ return c.id === clipId; });
if(!moving) return;
var sourceSlot = moving.currentSlot;
if(existing && existing.id !== clipId) existing.currentSlot = sourceSlot;
moving.currentSlot = targetSlotIdx;
renderMG();
});
$(document).off("dragover.spycMGPool").on("dragover.spycMGPool", "#spyc-mg-pool", function(e){ e.preventDefault(); });
$(document).off("drop.spycMGPool").on("drop.spycMGPool", "#spyc-mg-pool", function(e){
e.preventDefault();
if(!mgState) return;
var clipId = parseInt(e.originalEvent.dataTransfer.getData("text/plain"), 10);
if(isNaN(clipId)) return;
var clip = mgState.clips.find(function(c){ return c.id === clipId; });
if(clip) clip.currentSlot = -1;
renderMG();
});
$(document).off("click.spycMGFin").on("click.spycMGFin", "#spyc-mg-finish", function(){
if(!mgState) return;
var correct = mgState.clips.filter(function(c){ if(c.currentSlot < 0) return false; return mgState.slotOrder[c.currentSlot] === c.id; }).length;
var bonus = mgState.clips.length > 0 ? Math.round((correct / mgState.clips.length) * 15) : 0;
finalizeMontage(mgState.picked, bonus, false);
});
$(document).off("click.spycMGSkip").on("click.spycMGSkip", "#spyc-mg-skip", function(){
if(!mgState) return;
finalizeMontage(mgState.picked, 0, false);
});
function finalizeMontage(picked, miniBonus, skipped){
var qPC = V.PCMotherboard.img + V.PCcpu.img + V.PCgpu.img + V.PCram.img + V.PCstockage.img + V.PCos.img;
var qLabel, qClass, qMod;
if(qPC <= 6){ qLabel = "Mediocre"; qClass = "mediocre"; qMod = -15; }
else if(qPC <= 9){ qLabel = "Correct"; qClass = "correct"; qMod = -5; }
else if(qPC <= 12){ qLabel = "Good"; qClass = "good"; qMod = 0; }
else if(qPC <= 15){ qLabel = "Quality"; qClass = "quality"; qMod = 5; }
else { qLabel = "Excellent"; qClass = "excellent"; qMod = 10; }
var $pane = $('#spyc-app .spyc-pane[data-pane="editor"]');
$pane.append('<div class="spyc-overlay"><div class="spyc-modal"><div class="spyc-modal-ic">✓</div><div class="spyc-modal-t">Montage Confirmed</div><div class="spyc-modal-s">'+picked.length+' clips · PC quality: '+qLabel+'<br>Sending to Pending…</div></div></div>');
if(!V.SpycamMontages) V.SpycamMontages = [];
var idx = V.SpycamMontages.length + 1;
var name = "Montage_" + V.Day + "_" + (idx < 10 ? "0" + idx : "" + idx);
V.SpycamMontages.push({ name: name, thumb: picked[0].src, images: picked.map(function(p){ return {cam:p.cam, num:p.num, src:p.src}; }), imageCount: picked.length, qualityLabel: qLabel, qualityClass: qClass, qualityMod: qMod, miniBonus: miniBonus, miniSkipped: !!skipped, day: V.Day });
for(var i = 0; i < picked.length; i++){
var p = picked[i];
var camArr = V.SpycamUnlocked[p.cam] || [];
var pos = camArr.indexOf(p.num);
if(pos >= 0) camArr.splice(pos, 1);
V.SpycamUnlocked[p.cam] = camArr;
}
if(typeof V.Energy === "number") V.Energy = Math.max(0, V.Energy - 1);
V.FirstEditingSpycam = true;
mgState = null;
setTimeout(function(){ setup._SpycamSkipNextUpdate = true; Engine.play(currentPassage); }, 1800);
}
})();
<</script>>
<<script>>
setup.SpycamMaxImages = {
bathroom: 12,
housematefemale: 12,
housematemale: 0,
mainbedroom: 12
};
<</script>>
<div class="BottomUiBarCustom"><<BottomButton "Move">><<return [[↩️ Return|MCPC]]>><</BottomButton>></div><<sound "music" "music.music" true>>
/* ------------------------------------ BATHROOM ------------------------------------ */<<if $SpycamCurrentCam is "bathroom">>
<<passagebg>><img src="assets/img/misc/home/bathroom/bathroom.webp"/><</passagebg>><<if $Time == 0>><<sound "sfx" "sfx.shower" true>><<InformationUiPopUp "Spycam">>There is someone in front of the camera.<</InformationUiPopUp>>
<<set _Spycam = random(5)>><<if _Spycam is 0>><video src="assets/img/spycam/bathroom/07.mp4"/><<elseif _Spycam is 1>><video src="assets/img/spycam/bathroom/08.mp4"/><<elseif _Spycam is 2>><video src="assets/img/spycam/bathroom/09.mp4"/><<elseif _Spycam is 3>><video src="assets/img/spycam/bathroom/10.mp4"/><<elseif _Spycam is 4>><video src="assets/img/spycam/bathroom/11.mp4"/><<elseif _Spycam is 5>><video src="assets/img/spycam/bathroom/12.mp4"/><</if>><<elseif $Time == 2>><<sound "sfx" "sfx.shower" true>><<InformationUiPopUp "Spycam">>There is someone in front of the camera.<</InformationUiPopUp>><<set _Spycam = random(11)>>
<<set _Spycam = random(5)>><<if _Spycam is 0>><video src="assets/img/spycam/bathroom/01.mp4"/><<elseif _Spycam is 1>><video src="assets/img/spycam/bathroom/02.mp4"/><<elseif _Spycam is 2>><video src="assets/img/spycam/bathroom/03.mp4"/><<elseif _Spycam is 3>><video src="assets/img/spycam/bathroom/04.mp4"/><<elseif _Spycam is 4>><video src="assets/img/spycam/bathroom/05.mp4"/><<elseif _Spycam is 5>><video src="assets/img/spycam/bathroom/06.mp4"/><</if>><<else>><<InformationUiPopUp "Spycam">>There is currently nothing...<</InformationUiPopUp>><</if>>
/* ----------------------------- HOUSEMATE FEMALE ---------------------------- */<<elseif $SpycamCurrentCam is "housematefemale">>
<<passagebg>><<sound "bg" "bg.empty" true>><<if $Time !== 3>><img src="assets/img/misc/home/housematefemalebedroom.webp"/><<else>><img src="assets/img/misc/home/housematefemalebedroomnight.webp"/><</if>><</passagebg>><<if $Time !== 2>><<InformationUiPopUp "Spycam">>There is currently nothing...<</InformationUiPopUp>>
<<else>><<InformationUiPopUp "Spycam">>There is someone in front of the camera.<</InformationUiPopUp>>
<<set _Spycam = random(11)>><<if _Spycam is 0>><video src="assets/img/spycam/housematefemale/01.mp4"/><<elseif _Spycam is 1>><video src="assets/img/spycam/housematefemale/02.mp4"/><<elseif _Spycam is 2>><video src="assets/img/spycam/housematefemale/03.mp4"/><<elseif _Spycam is 3>><video src="assets/img/spycam/housematefemale/04.mp4"/><<elseif _Spycam is 4>><video src="assets/img/spycam/housematefemale/05.mp4"/><<elseif _Spycam is 5>><video src="assets/img/spycam/housematefemale/06.mp4"/><<elseif _Spycam is 6>><video src="assets/img/spycam/housematefemale/07.mp4"/><<elseif _Spycam is 7>><video src="assets/img/spycam/housematefemale/08.mp4"/><<elseif _Spycam is 8>><video src="assets/img/spycam/housematefemale/09.mp4"/><<elseif _Spycam is 9>><video src="assets/img/spycam/housematefemale/10.mp4"/><<elseif _Spycam is 10>><video src="assets/img/spycam/housematefemale/11.mp4"/><<elseif _Spycam is 11>><video src="assets/img/spycam/housematefemale/12.mp4"/><</if>>
<</if>>
/* ------------------------------ HOUSEMATE MALE ------------------------------ */<<elseif $SpycamCurrentCam is "housematemale">>
<<passagebg>><<sound "bg" "bg.empty" true>><<if $Time !== 3>><img src="assets/img/misc/home/housematemalebedroom.webp"/><<else>><img src="assets/img/misc/home/housematemalebedroomnight.webp"/><</if>><</passagebg>><<InformationUiPopUp "Spycam">>There is currently nothing...<</InformationUiPopUp>>
/* ------------------------------- MAIN BEDROOM ------------------------------- */<<elseif $SpycamCurrentCam is "mainbedroom">>
<<passagebg>><<sound "bg" "bg.empty" true>><<if $Time !== 3>><img src="assets/img/misc/home/mainbedroom.webp"/><<else>><img src="assets/img/misc/home/mainbedroomnight.webp"/><</if>><</passagebg>><<if $Time !== 0>><<InformationUiPopUp "Spycam">>There is currently nothing...<</InformationUiPopUp>>
<<else>><<InformationUiPopUp "Spycam">>There is someone in front of the camera.<</InformationUiPopUp>>
<<set _Spycam = random(11)>><<if _Spycam is 0>><video src="assets/img/spycam/mainbedroom/01.mp4"/><<elseif _Spycam is 1>><video src="assets/img/spycam/mainbedroom/02.mp4"/><<elseif _Spycam is 2>><video src="assets/img/spycam/mainbedroom/03.mp4"/><<elseif _Spycam is 3>><video src="assets/img/spycam/mainbedroom/04.mp4"/><<elseif _Spycam is 4>><video src="assets/img/spycam/mainbedroom/05.mp4"/><<elseif _Spycam is 5>><video src="assets/img/spycam/mainbedroom/06.mp4"/><<elseif _Spycam is 6>><video src="assets/img/spycam/mainbedroom/07.mp4"/><<elseif _Spycam is 7>><video src="assets/img/spycam/mainbedroom/08.mp4"/><<elseif _Spycam is 8>><video src="assets/img/spycam/mainbedroom/09.mp4"/><<elseif _Spycam is 9>><video src="assets/img/spycam/mainbedroom/10.mp4"/><<elseif _Spycam is 10>><video src="assets/img/spycam/mainbedroom/11.mp4"/><<elseif _Spycam is 11>><video src="assets/img/spycam/mainbedroom/12.mp4"/><</if>>
<</if>>
/* -------------------------------------- END -------------------------------------- */<</if>>
<div class="BottomUiBarCustom">
<<BottomButton "Move">><<link "↩️ Return">><<goto "SpycamSoftware">><</link>><</BottomButton>>
</div><<sound "music" "music.music" true>><<sound "bg" "bg.empty" true>><<passagebg>><<if $Time !== 3>><img src="assets/img/misc/university/universitypersonaloffice.webp"/><<else>><img src="assets/img/misc/university/universitypersonalofficenight.webp"/><</if>><</passagebg>><style>
#grid5-app{--red:rgb(230,87,99);--red-border:rgba(230,87,99,.40);--surface:rgba(0,0,0,.30);--surface-hover:rgba(0,0,0,.45);--border:rgba(255,255,255,.10);--border-hover:rgba(230,87,99,.45);--text:rgba(255,255,255,.93);--text-desc:rgba(255,255,255,.62);--text-muted:rgba(255,255,255,.28);--locked-bg:rgba(0,0,0,.45);--locked-border:rgba(255,255,255,.05);padding:18px;color:var(--text);}
#grid5-app *{box-sizing:border-box;}
.g5-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:14px;}
.g5-card{padding:22px 20px;min-height:140px;border-radius:11px;border:1px solid var(--border);background:var(--surface);cursor:pointer;transition:background .15s,border-color .15s,transform .13s,box-shadow .15s;display:flex;flex-direction:column;gap:8px;position:relative;overflow:hidden;}
.g5-card::before{content:"";position:absolute;left:0;top:0;bottom:0;width:3px;background:var(--red);opacity:0;transition:opacity .15s;border-radius:11px 0 0 11px;}
.g5-card:hover{background:var(--surface-hover);border-color:var(--border-hover);transform:translateY(-2px);box-shadow:0 8px 24px rgba(0,0,0,.55);}
.g5-card:hover::before{opacity:1;}
.g5-card:active{transform:scale(.98);box-shadow:none;}
.g5-card-title{font-size:calc(16px + var(--font-boost,0px));font-weight:800;color:var(--text);line-height:1.25;letter-spacing:.01em;}
.g5-card-desc{font-size:calc(14px + var(--font-boost,0px));font-weight:500;color:var(--text-desc);line-height:1.5;flex:1 1 auto;}
.g5-card-arrow{font-size:calc(16px + var(--font-boost,0px));color:var(--red);text-align:right;font-weight:900;opacity:.80;margin-top:auto;transition:opacity .15s;}
.g5-card:hover .g5-card-arrow{opacity:1;}
.g5-card.is-locked{cursor:not-allowed;pointer-events:none;background:var(--locked-bg);border-color:var(--locked-border);}
.g5-card.is-locked::before{display:none;}
.g5-card.is-locked .g5-card-title{color:var(--text-muted);}
.g5-card.is-locked .g5-card-desc{color:rgba(255,255,255,.22);}
.g5-card-unlock-hint{font-size:calc(14px + var(--font-boost,0px));font-weight:700;color:rgba(230,87,99,.70);line-height:1.3;}
.g5-card-unlock-hint:first-of-type{margin-top:auto;}
.g5-card-unlock-progress{font-size:calc(14px + var(--font-boost,0px));font-weight:900;color:rgba(255,255,255,.35);font-family:'JetBrains Mono','Fira Code',Consolas,monospace;}
.g5-card-unlock-progress span{color:rgba(230,87,99,.80);}
.g5-lock-badge{position:absolute;top:12px;right:13px;font-size:calc(13px + var(--font-boost,0px));opacity:.30;}
@media(max-width:800px){.g5-grid{grid-template-columns:repeat(2,1fr);}.g5-card{min-height:110px;padding:18px 16px;}}
@media(max-width:480px){.g5-grid{grid-template-columns:1fr;}.g5-card{min-height:90px;padding:16px 14px;}}
</style><div id="grid5-app"></div><<script>>
setTimeout(function(){
var V = State.variables;
var cards = [
{
title: "Give a class",
desc: "You give a class and earn money, nothing simpler.",
passage: "EVENT_UniversityClass1",
conditions: [
{ check: V.Time < 3, hint: "It's too late to do this." },
]
},
{
title: "Give private lessons",
desc: "Organize a private lesson with certain students and earn money.",
passage: "EVENT_UniversityClass2",
conditions: [
{ check: V.MakeUniversityClass1 >= 5, hint: "You must give 5 classes", need: 5, current: V.MakeUniversityClass1 },
{ check: V.Time < 3, hint: "It's too late to do this" },
{ check: V.PsychicPower >= 1, hint: "You don't have enough Psychic Power" },
]
},
{
title: "Punish a student",
desc: "Call a student to punish her for her poor results.",
passage: "EVENT_UniversityClass3",
conditions: [
{ check: V.MakeUniversityClass2 >= 5, hint: "You must give 5 private lessons", need: 5, current: V.MakeUniversityClass2 },
{ check: V.Time < 2, hint: "It's too late to do this" },
{ check: V.PsychicPower >= 1, hint: "You don't have enough Psychic Power" },
]
},
{
title: "Private intensive revision",
desc: "Set up a private revision session with a student, then take advantage of her.",
passage: "EVENT_UniversityClass4",
conditions: [
{ check: V.Corruption.university >= 2, hint: "You must raise the university corruption to level 2", need: 2, current: V.Corruption.university },
{ check: V.MakeUniversityClass3 >= 5, hint: "You must give 5 punish student", need: 5, current: V.MakeUniversityClass3 },
{ check: V.Time < 3, hint: "It's too late to do this" },
{ check: V.PsychicPower >= 1, hint: "You don't have enough Psychic Power" },
]
},
{
title: "Group intensive revision",
desc: "Set up a group revision session with several students, then take advantage of them.",
passage: "EVENT_UniversityClass5",
conditions: [
{ check: V.Corruption.university >= 3, hint: "You must raise the university corruption to level 3", need: 3, current: V.Corruption.university },
{ check: V.MakeUniversityClass4 >= 5, hint: "You must give 5 private intensive revision", need: 5, current: V.MakeUniversityClass4 },
{ check: V.Time < 3, hint: "It's too late to do this" },
{ check: V.PsychicPower >= 1, hint: "You don't have enough Psychic Power" },
]
},
{
title: "Private practical anatomy class",
desc: "Give a private class under the pretense of learning anatomy, ultimately ending up having sex with the student.",
passage: "EVENT_UniversityClass6",
conditions: [
{ check: V.Corruption.university >= 4, hint: "You must raise the university corruption to level 4", need: 4, current: V.Corruption.university },
{ check: V.MakeUniversityClass5 >= 5, hint: "You must give 5 group intensive revision", need: 5, current: V.MakeUniversityClass5 },
{ check: V.Time < 3, hint: "It's too late to do this" },
{ check: V.PsychicPower >= 1, hint: "You don't have enough Psychic Power" },
]
},
{
title: "Group practical anatomy class",
desc: "Give a group class under the pretense of learning anatomy, ultimately ending up having sex with the students.",
passage: "EVENT_UniversityClass7",
conditions: [
{ check: V.Corruption.university >= 5, hint: "You must raise the university corruption to level 5", need: 5, current: V.Corruption.university },
{ check: V.MakeUniversityClass6 >= 5, hint: "You must give 5 private practical anatomy class", need: 5, current: V.MakeUniversityClass6 },
{ check: V.Time < 3, hint: "It's too late to do this" },
]
}
];
var app = document.getElementById("grid5-app");
if(!app) return;
var gridEl = document.createElement("div");
gridEl.className = "g5-grid";
cards.forEach(function(card){
var cardUnlocked = true;
if(card.conditions && card.conditions.length > 0){
cardUnlocked = card.conditions.every(function(c){ return !!c.check; });
}
var cardEl = document.createElement("div");
cardEl.className = "g5-card" + (cardUnlocked ? "" : " is-locked");
if(!cardUnlocked){
var badge = document.createElement("span");
badge.className = "g5-lock-badge";
badge.textContent = "🔒";
cardEl.appendChild(badge);
}
var titleEl = document.createElement("div");
titleEl.className = "g5-card-title";
titleEl.textContent = card.title;
cardEl.appendChild(titleEl);
var descEl = document.createElement("div");
descEl.className = "g5-card-desc";
descEl.textContent = card.desc;
cardEl.appendChild(descEl);
if(!cardUnlocked && card.conditions){
var firstHint = true;
card.conditions.forEach(function(c){
if(!!c.check) return;
if(c.hint){
var hintEl = document.createElement("div");
hintEl.className = "g5-card-unlock-hint";
if(firstHint){ hintEl.style.marginTop = "auto"; firstHint = false; }
hintEl.textContent = c.hint;
cardEl.appendChild(hintEl);
}
if(c.need !== undefined && c.current !== undefined){
var progEl = document.createElement("div");
progEl.className = "g5-card-unlock-progress";
progEl.innerHTML = "<span>" + c.current + "</span> / " + c.need;
cardEl.appendChild(progEl);
}
});
}
if(cardUnlocked){
var arrow = document.createElement("div");
arrow.className = "g5-card-arrow";
arrow.textContent = "➜";
cardEl.appendChild(arrow);
cardEl.addEventListener("click", function(){
Engine.play(card.passage);
});
}
gridEl.appendChild(cardEl);
});
app.appendChild(gridEl);
}, 1);
<</script>>
<div class="BottomUiBarCustom"><<if $Time !== 3>><<if $NPCPrincipal.lastCorruptBool == false>><<if $NPCPrincipal.lvl == 1 && $PsychicPower >= 1>><<BottomButton "Action">><<link "⏳ Wait">><<set $FromOtherPlace = true>><<SetReturnTo>><<set $ActiveNPC = $NPCPrincipal>><<goto "Talk.Principal">><</link>><</BottomButton>><<elseif $NPCPrincipal.lvl == 3 && $PsychicPower >= 1>><<BottomButton "Action">><<link "⏳ Wait">><<set $FromOtherPlace = true>><<SetReturnTo>><<set $ActiveNPC = $NPCPrincipal>><<goto "Talk.Principal">><</link>><</BottomButton>><<elseif $NPCPrincipal.lvl == 4 && $PsychicPower >= 1 && $PrincipalMeeting4Confirm == true>><<BottomButton "Action">><<link "⏳ Wait">><<set $FromOtherPlace = true>><<SetReturnTo>><<set $ActiveNPC = $NPCPrincipal>><<goto "Talk.Principal">><</link>><</BottomButton>><<elseif ($NPCPrincipal.lvl == 1 or $NPCPrincipal.lvl == 3 or $NPCPrincipal.lvl == 4) and $PsychicPower <= 0>><<BottomButton "Action">><<link "🔒 Not enough Psychic Power">><</link>><</BottomButton>><</if>><<elseif ($NPCPrincipal.lvl == 1 or $NPCPrincipal.lvl == 3 or $NPCPrincipal.lvl == 4) and $NPCPrincipal.lastCorruptBool == true>><<BottomButton "Action">><<link "🌙 Already Influenced Today">><</link>><</BottomButton>><</if>><</if>>
<<BottomButton "Move">>[[🚪 Exit|UniversityStaffRoom]]<</BottomButton>>
</div><<passagebg>><<sound "bg" "bg.empty" true>><img src="assets/img/misc/neighborhood/principal/homenight.webp"/><</passagebg>><<set _npc = $NPCPrincipal>>
<<InformationUiPopUp>>I arrive outside her place. Barely at the door, she opens it before I even knock, already smiling. She steps aside to let me in and I follow her into the living room. The house is warm and quiet, candles already lit on the coffee table, music in the background. She points me toward the couch and I sit down. She settles right beside me, close.
<</InformationUiPopUp>>
<<TalkNPC _npc "I'm glad you came, Master.">>
<<TalkMC "You took a long time to get everything ready.">>
<<TalkNPC _npc "I needed time to put together the idea I had in mind.">>
<<TalkMC "And did you manage it?">>
<<TalkNPC _npc "Yes, you'll see, you're going to love it.">>
<<TalkNPC _npc "Can I get you something to drink first?">>
<<TalkMC "Whatever you have.">>
<<InformationUiPopUp>>She gets up and comes back with two glasses of champagne, hands me one, and sits back down beside me. Even closer this time.
<</InformationUiPopUp>>
<<TalkNPC _npc "I've done nothing but think about you since last time. I couldn't wait any longer for this evening.">>
<<TalkMC "What were you thinking about?">>
<<TalkNPC _npc "What you were going to do to me.">>
<<TalkMC "Tell me.">>
<<TalkNPC _npc "I want you to hurt me. And to take a lot of pleasure. And I want you not to stop until I truly can't take any more.">>
<<TalkMC "You want to do it here, now?">>
<<TalkNPC _npc "No, I want to take you downstairs, Master. I've prepared something, that's why it took me so long.">>
<<TalkNPC _npc "Follow me, please, Master.">>
<<revealtext "follow">><<passagebg>><<sound "bg" "bg.empty" true>><img src="assets/img/misc/neighborhood/principal/basement.webp"/><</passagebg>><<InformationUiPopUp>>She empties her glass quickly, sets it on the table, and stands. She holds out her hand. I take it and she leads me to the cellar door, opens it, and we go down. The room below is dimly lit. A rope coiled on a hook, a wooden crate positioned in the center, equipment laid out along the wall with a clear purpose. She stops in the middle of the room and turns back toward me, hands clasped in front of her.
<</InformationUiPopUp>>
<<TalkNPC _npc "I want you to tie me up, Master. Use me however you please. I've been thinking about this for so long.">>
<<TalkMC "As you wish.">>
<<TalkMC "Undress first.">>
<<TalkNPC _npc "Yes, Master.">>
<<InformationUiPopUp>>She undresses completely without hesitating, standing in front of me with nothing hidden. I take the rope and position myself behind her, binding her wrists firmly together behind her back, then passing the rope forward around her chest, framing and tightening around her tits. Then a second rope for her ankles. She stays perfectly still through every second, breathing slowly and steadily, eyes closed.
<</InformationUiPopUp>>
<<TalkNPC _npc "Thank you, Master. This is exactly what I dreamed of.">>
<<TalkMC "Get on the crate, on your knees, head forward.">>
<<TalkNPC _npc "Yes, Master.">>
<<InformationUiPopUp>>I guide her onto the wooden crate, positioning her on her knees with her torso leaning forward, cheek resting against the surface, arms bound behind her back, completely exposed. I let my hand slide slowly over her ass, running over her body without rushing. She doesn't move.
<</InformationUiPopUp>>
<<TalkMC "Stay completely still. Don't move for any reason.">>
<<TalkNPC _npc "Yes, Master. I will. I promise.">>
<<InformationUiPopUp>>I slap her ass firmly. The sound fills the room. She lets out a short broken breath, staying locked in position.
<</InformationUiPopUp>>
<video src="assets/img/story/character/principal/5/01.mp4"/>
<<TalkNPC _npc "Hah, again, Master. Please, again.">>
<<TalkMC "When I decide. Not when you ask.">>
<<TalkNPC _npc "Yes. Sorry, Master.">>
<<InformationUiPopUp>>I position myself behind her and push my cock slowly and firmly into her ass. She exhales a long fractured breath, her fingers gripping hard in her back against the rope.
<</InformationUiPopUp>>
<video src="assets/img/story/character/principal/5/02.mp4"/>
<<TalkNPC _npc "<em>Ah... mmh... fuck...</em>">>
<<TalkNPC _npc "Hnn, yes, Master, yes, please.">>
<<TalkMC "Take it, don't make a sound.">>
<<TalkNPC _npc "I, hnng, I'll try, Master.">>
<<TalkMC "Try harder.">>
<<TalkNPC _npc "Mm. Yes, Master.">>
<<InformationUiPopUp>>I pull out slowly and change position, pushing into her pussy. She shudders immediately, her whole body reacting to the change, a broken breath escaping before she can stop it.
<</InformationUiPopUp>>
<video src="assets/img/story/character/principal/5/03.mp4"/>
<<TalkNPC _npc "<em>Ah... yes... fuck...</em>">>
<<TalkNPC _npc "Master, please, harder, I need it harder, please.">>
<<TalkMC "Ask properly.">>
<<TalkNPC _npc "Please, Master. Harder. I beg you. Please.">>
<<TalkMC "That's already much better.">>
<<TalkNPC _npc "Hah, thank you, Master.">>
<<InformationUiPopUp>>I grab her bound arms and use them to pull her torso fully upright, pushing harder while holding her by her own restraints. Grabbing her by the throat from time to time.
<</InformationUiPopUp>>
<video src="assets/img/story/character/principal/5/04.mp4"/>
<<TalkNPC _npc "<em>Ah... ah... yes... yes...</em>">>
<<TalkNPC _npc "Yes, yes, Master, yes, like that, don't stop, please.">>
<<TalkMC "No, open your mouth instead.">>
<<TalkNPC _npc "Yes, Master, whatever you want.">>
<<InformationUiPopUp>>I release her arms and let her fall back against the crate. I come around to the front. She lifts her head before I even get there and opens her mouth wide, tongue out, impatiently waiting for my cock.
<</InformationUiPopUp>>
<video src="assets/img/story/character/principal/5/05.mp4"/>
<<TalkNPC _npc "<em>Glrk... mmh... ghlk...</em>">>
<<TalkNPC _npc "Mm, mmh.">>
<<TalkMC "Deeper.">>
<<TalkNPC _npc "Mmph.">>
<<TalkMC "Good, hold it like that.">>
<<TalkNPC _npc "Mmm.">>
<<InformationUiPopUp>>I go back behind her and push my cock back into her pussy, gripping her hips hard, setting a brutal rhythm from the start.
<</InformationUiPopUp>>
<video src="assets/img/story/character/principal/5/06.mp4"/>
<<TalkNPC _npc "<em>Ah... fuck... more...</em>">>
<<TalkNPC _npc "Master, please, don't stop, I don't want you to stop, please.">>
<<TalkMC "Shut it.">>
<<TalkNPC _npc "Yes, Master. Sorry, Master.">>
<<InformationUiPopUp>>Then I switch to her ass and she moans deeply, her forehead dropping heavily against the surface of the crate.
<</InformationUiPopUp>>
<video src="assets/img/story/character/principal/5/07.mp4"/>
<<TalkNPC _npc "<em>Ah... mmh... fuck...</em>">>
<<TalkNPC _npc "Master, it's so deep, hah.">>
<<InformationUiPopUp>>I keep going in her ass, relentless.
<</InformationUiPopUp>>
<video src="assets/img/story/character/principal/5/08.mp4"/>
<<TalkNPC _npc "<em>Ah... ah... yes... yes...</em>">>
<<TalkNPC _npc "Master, I, please, more, I need more.">>
<<TalkMC "You want more?">>
<<TalkNPC _npc "Yes, Master, please, I need more, give me more please.">>
<<TalkMC "Then take it.">>
<<TalkNPC _npc "Hah, hah, yes, Master, thank you.">>
<<InformationUiPopUp>>I push harder and deeper into her ass, driving her to the absolute limit of what she can take. She holds through every second, a continuous broken sound escaping her with every thrust.
<</InformationUiPopUp>>
<video src="assets/img/story/character/principal/5/09.mp4"/>
<<TalkNPC _npc "<em>Ah... fuck... yes...</em>">>
<<InformationUiPopUp>>I pull out slowly. I take a plug from the equipment nearby, then push it into her ass.
<</InformationUiPopUp>>
<video src="assets/img/story/character/principal/5/10.mp4"/>
<<TalkNPC _npc "Oh, Master. I love it. It feels so good, hah.">>
<<InformationUiPopUp>>With the plug still in her ass, I push into her pussy. The fullness makes her cry out immediately and without any restraint.
<</InformationUiPopUp>>
<video src="assets/img/story/character/principal/5/11.mp4"/>
<<TalkNPC _npc "<em>Ah... ah... fuck...</em>">>
<<TalkNPC _npc "Master it's, it's too much, I can't, hah, hah.">>
<<TalkMC "Yes you can, you need to hold it.">>
<<TalkNPC _npc "Yes. Yes, Master.">>
<<TalkMC "Good little slut.">>
<<TalkNPC _npc "Thank you, Master, hnn.">>
<<InformationUiPopUp>>I reach forward and slowly pull the plug out. I set it on the crate right beside her face. Without me telling her to, without any hesitation, she opens her mouth and licks the plug with her tongue while I keep fucking her.
<</InformationUiPopUp>>
<video src="assets/img/story/character/principal/5/12.mp4"/>
<<TalkNPC _npc "<em>Ah... mmh... yes...</em>">>
<<TalkMC "You're really one hell of a slut.">>
<<TalkNPC _npc "Hah, thank you, Master. Thank you.">>
<<InformationUiPopUp>>I grab her bound arms again and pull, fucking her pussy harder, her back arching completely.
<</InformationUiPopUp>>
<video src="assets/img/story/character/principal/5/13.mp4"/>
<<TalkNPC _npc "<em>Ah... fuck... more...</em>">>
<<TalkNPC _npc "Master, please, I can't, it's so good, hah, don't stop please, please.">>
<<InformationUiPopUp>>I release her arms and let her fall forward, then press one hand firmly on her head and push her face against the crate. Then I fuck her ass again.
<</InformationUiPopUp>>
<video src="assets/img/story/character/principal/5/14.mp4"/>
<<TalkNPC _npc "<em>Mmph... mmph...</em>">>
<<TalkNPC _npc "Mmph, mmph, Master.">>
<<TalkMC "We're changing position now. Don't move while I take care of this.">>
<<TalkNPC _npc "Hah, yes, Master. Whatever you want.">>
<<TalkMC "I'm just retying your wrists.">>
<<TalkNPC _npc "Yes, Master. I trust you. Completely.">>
<<InformationUiPopUp>>I undo the ankle rope first, then the ropes around her chest and wrists. I retie her wrists together with a single rope, then guide her to stand and hook the rope above her on a hook so her arms are raised and suspended above her head. She stays perfectly still, waiting for me to take care of her again.
<</InformationUiPopUp>>
<video src="assets/img/story/character/principal/5/15.mp4"/>
<<TalkMC "You look incredible like this, body bare, completely open.">>
<<TalkNPC _npc "I'm ready, Master. Please fuck me like the bitch I am.">>
<<InformationUiPopUp>>I position myself at her side, lift one of her legs with my arm, and push into her pussy. Her leg lifted while I fuck her, suspended by her wrists above her head.
<</InformationUiPopUp>>
<video src="assets/img/story/character/principal/5/16.mp4"/>
<<TalkNPC _npc "<em>Ah... mmh... yes...</em>">>
<<TalkNPC _npc "Master, yes, hah, exactly like that, don't stop please.">>
<<InformationUiPopUp>>I push harder, holding her leg up, her whole body swaying with every thrust.
<</InformationUiPopUp>>
<video src="assets/img/story/character/principal/5/17.mp4"/>
<<TalkNPC _npc "<em>Ah... ah... yes... yes...</em>">>
<<TalkNPC _npc "Hah, hah, Master, yes, please, don't stop please.">>
<<TalkMC "I love your big ass way too much, I'm going to fuck it again.">>
<<TalkNPC _npc "Hah, yes, Master. Please.">>
<<InformationUiPopUp>>Still at her side, I shift and push my cock into her ass.
<</InformationUiPopUp>>
<video src="assets/img/story/character/principal/5/18.mp4"/>
<<TalkNPC _npc "<em>Ah... fuck... it's so deep...</em>">>
<<TalkNPC _npc "Master, hah, hah, it's so deep like this.">>
<<InformationUiPopUp>>I push even harder into her ass while rubbing her pussy with my fingers, her leg still raised, the rope above taking her full weight while she loses control.
<</InformationUiPopUp>>
<video src="assets/img/story/character/principal/5/19.mp4"/>
<<TalkNPC _npc "<em>Ah... ah... yes... fuck...</em>">>
<<TalkNPC _npc "Hah, Master, hah, fuck, it's so good.">>
<<TalkMC "I've told you several times to shut it. Mmmmmm... I have something for that.">>
<<InformationUiPopUp>>I unhook her wrists from above and move her onto her back on the crate. I position her so her legs fold completely back toward her head, her arms looping over her own legs, each one tied with the ropes to keep her from moving. Then I put a gag in her mouth. She's completely locked in place, unable to speak, her pussy and ass wide open.
<</InformationUiPopUp>>
<video src="assets/img/story/character/principal/5/20.mp4"/>
<<TalkMC "That's perfect like this.">>
<<InformationUiPopUp>>I take the vibrator from the equipment nearby and position myself in front of her, pressing it against her pussy. She shudders violently at the first contact, desperate muffled sounds escaping immediately against the gag.
<</InformationUiPopUp>>
<video src="assets/img/story/character/principal/5/21.mp4"/>
<<TalkNPC _npc "<em>Mmph... mmh... mmph...</em>">>
<<InformationUiPopUp>>I come around to the front of the crate, keeping the vibrator pressed against her pussy with one hand, and end up fucking her ass.
<</InformationUiPopUp>>
<video src="assets/img/story/character/principal/5/22.mp4"/>
<<TalkNPC _npc "<em>Mmph... mmh... mmph...</em>">>
<<InformationUiPopUp>>I push harder into her ass, the vibrator remaining firmly pressed against her pussy without letting up. Her whole body completely given over, taking everything without being able to do anything, muffled sounds escaping against the gag with every thrust. Then I take her hair to hold her head up.
<</InformationUiPopUp>>
<video src="assets/img/story/character/principal/5/23.mp4"/>
<<TalkNPC _npc "<em>Mmph... mmh... mmph...</em>">>
<<InformationUiPopUp>>I pull out the vibrator and fuck her pussy directly, still holding her head by the hair, pushing hard and deep without pause. Her whole body moving in rhythm with every thrust.
<</InformationUiPopUp>>
<video src="assets/img/story/character/principal/5/24.mp4"/>
<<TalkNPC _npc "<em>Mmph... mmh... mmph...</em>">>
<<InformationUiPopUp>>I switch back to her ass, pushing deep and fast, her mouth starting to drool. Then I slow to a complete stop and pull out. I step back and watch her come back to herself. She stays locked in position, gagged, completely flushed.
<</InformationUiPopUp>>
<video src="assets/img/story/character/principal/5/25.mp4"/>
<<TalkNPC _npc "<em>Mmph... mmh...</em>">>
<video src="assets/img/story/character/principal/5/26.mp4"/>
<<TalkMC "Good little slut, you held perfectly.">>
<<InformationUiPopUp>>I remove the gag and untie her wrists. She catches her breath in long slow inhales mixed with a lot of pleasure, blinking, and looks up at me with a gaze full of pleasure and completely submissive.
<</InformationUiPopUp>>
<<TalkNPC _npc "Master.">>
<<TalkMC "How do you feel?">>
<<TalkNPC _npc "I feel, hah, I feel completely yours. Every part of me.">>
<<TalkNPC _npc "I love this. I love it so much.">>
<<TalkMC "Get on your knees. Now it's my turn to finish.">>
<<TalkNPC _npc "Yes, Master. Please. Come on my face please, Master. Please.">>
<<InformationUiPopUp>>She immediately slides off the crate and kneels in front of me, bouncing her tits with her hands, eyes fixed on mine, mouth wide open with her tongue out, desperate and pleading.
<</InformationUiPopUp>>
<<TalkNPC _npc "Please, Master. Give me everything. I want it so much. Please. I beg you. Please, Master. Please.">>
<<InformationUiPopUp>>I end up coming on her face and chest. She keeps her eyes open, still, hands still holding her tits, taking all my cum until I'm completely done.
<</InformationUiPopUp>>
<video src="assets/img/story/character/principal/5/27.mp4"/>
<<TalkNPC _npc "Thank you, Master. I love you so much, Master.">>
<<TalkMC "Good girl.">>
<<InformationUiPopUp>>She stays on her knees for a long moment, breathing slowly. Then she looks up at me with an exhausted but completely submissive and satisfied expression. The cellar is warm and quiet around us.
<</InformationUiPopUp>><</revealtext>>
<div class="BottomUiBarCustom">
<<BottomButton "Decision">><<revealbtn "follow" "➡️ Follow" "moveBtn">><</revealbtn>><</BottomButton>>
<<if $PrincipalChapter6End == false>><<BottomButton "Move" "moveBtn">><<link "↩️ Return">><<goto "PrincipalHome">><<set $PrincipalChapter6End = true>><</link>><</BottomButton>><<elseif $PrincipalChapter6End == true>><<BottomButton "Move" "moveBtn">><<link "↩️ Return">><<goto "Principal.interact">><</link>><</BottomButton>><</if>>
</div><<sound "music" "music.music" true>><<passagebg>><<if $Time !== 3>><<sound "bg" "bg.classroom" true>><img src="assets/img/misc/university/class1.webp"/><<else>><<sound "bg" "bg.empty" true>><img src="assets/img/misc/university/class1night.webp"/><</if>><</passagebg>><<set _used = []>><<set _npcCount = 2>><<set _npc1Img = 0>><<set _npc2Img = 0>><<set _npc3Img = 0>><<if _npcCount >= 1>><<set _npc1Img = random(1, 8)>><<set _used.push(_npc1Img)>><</if>><<if _npcCount >= 2>><<set _npc2Img = random(1, 8)>><<for ; _used.includes(_npc2Img) ; >><<set _npc2Img = random(1, 8)>><</for>><<set _used.push(_npc2Img)>><</if>><<if _npcCount >= 3>><<set _npc3Img = random(1, 8)>><<for ; _used.includes(_npc3Img) ; >><<set _npc3Img = random(1, 8)>><</for>><<set _used.push(_npc3Img)>><</if>><<set _img1 = "assets/img/character/npc/G" + _npc1Img + ".jpg">><<set _img2 = "assets/img/character/npc/G" + _npc2Img + ".jpg">><<set _img3 = "assets/img/character/npc/G" + _npc3Img + ".jpg">>
<<InformationUiPopUp>>The classroom is full. The students are settled in, notebooks open, pens ready. I take my place in front of the board and the class begins.
<</InformationUiPopUp>>
<<TalkMC "Open your notes to the previous chapter. Today we're going further.">>
<<TalkRandom "Student" _img1 "We stopped at section three, right?">>
<<TalkMC "Exactly. And this time I expect real answers.">>
<<InformationUiPopUp>>After a while, the end of class arrives.
<</InformationUiPopUp>>
<<TalkRandom "Student" _img1 "You explain really well, it's so much clearer than with the other professors.">>
<<TalkMC "Remember that for the exam. See you next class.">>
<<InformationUiPopUp>>The room empties gradually. An hour well spent.
<</InformationUiPopUp>>
<<InformationUiPopUp "Bank" #f1c40f>><em>+$150 Bank</em>
<</InformationUiPopUp>>
<<InformationUiPopUp "Energy" #f1c40f>><em>-1 Energy</em>
<</InformationUiPopUp>>
<div class="BottomUiBarCustom">
<<BottomButton "Move">><<link "↩️ Return">><<goto "UniversityPersonalOffice">><<set $Time++>><<set $Bank += 200>><<set $Energy-->><<set $MakeUniversityClass1++>><</link>><</BottomButton>>
</div><<sound "music" "music.music" true>><<sound "bg" "bg.empty" true>><<passagebg>><<if $Time !== 3>><img src="assets/img/misc/university/universitypersonaloffice.webp"/><<else>><img src="assets/img/misc/university/universitypersonalofficenight.webp"/><</if>><</passagebg>><<set _used = []>><<set _npcCount = 1>><<set _npc1Img = 0>><<set _npc2Img = 0>><<set _npc3Img = 0>><<if _npcCount >= 1>><<set _npc1Img = random(1, 8)>><<set _used.push(_npc1Img)>><</if>><<if _npcCount >= 2>><<set _npc2Img = random(1, 8)>><<for ; _used.includes(_npc2Img) ; >><<set _npc2Img = random(1, 8)>><</for>><<set _used.push(_npc2Img)>><</if>><<if _npcCount >= 3>><<set _npc3Img = random(1, 8)>><<for ; _used.includes(_npc3Img) ; >><<set _npc3Img = random(1, 8)>><</for>><<set _used.push(_npc3Img)>><</if>><<set _img1 = "assets/img/character/npc/G" + _npc1Img + ".jpg">><<set _img2 = "assets/img/character/npc/G" + _npc2Img + ".jpg">><<set _img3 = "assets/img/character/npc/G" + _npc3Img + ".jpg">>
<<InformationUiPopUp>>I'm in my office. A student knocks and comes in, bag against her chest, looking slightly stressed.
<</InformationUiPopUp>>
<<TalkRandom "Student" _img1 "Thank you for seeing me. I'm really lost on the last two chapters.">>
<<TalkMC "Sit down. We'll go back to the beginning of what's giving you trouble.">>
<<TalkRandom "Student" _img1 "I don't understand why I can't retain it, I do read the notes.">>
<<TalkMC "Reading and understanding aren't the same thing. Show me your notes.">>
<<TalkRandom "Student" _img1 "That's where it all falls apart for me, that section right there.">>
<<TalkMC "Normal. Everyone gets stuck here. Look, let's break it down differently.">>
<<TalkRandom "Student" _img1 "Oh, yeah, when you put it like that it's so much simpler.">>
<<TalkMC "Let's do it again with a different example, and you explain it back to me.">>
<<InformationUiPopUp>>After several minutes helping her, we're getting close to the end, but I can see she's still very stressed. I could use my power to change that.
<</InformationUiPopUp>>
<<revealtext "power">><<InformationUiPopUp "Psychic Power" #7aa2ff>>You decide to use your power.
<em>-1 Psychic Power</em><</InformationUiPopUp>>
<<TalkMC "Listen.">>
<<TalkMC "From now on you'll feel good, more at ease, relaxed. You'll enjoy that feeling, and it'll help you understand your courses better.">>
<<InformationUiPopUp>>After a few seconds of stillness, she comes back to herself little by little.
<</InformationUiPopUp>>
<<TalkRandom "Student" _img1 "Hmm...">>
<<TalkRandom "Student" _img1 "Could I come back next time? It really helps.">>
<<TalkMC "We'll see. For now work on what we covered today.">>
<<set _random = random(1)>><<if _random == 0>>
<img src="assets/img/events/university/basic/1.webp"/>
<<elseif _random == 1>>
<img src="assets/img/events/university/basic/2.webp"/>
<</if>>
<<InformationUiPopUp>>She leaves with her notes, noticeably more relaxed.
<</InformationUiPopUp>>
<<InformationUiPopUp "Bank" #f1c40f>><em>+$100 Bank</em>
<</InformationUiPopUp>>
<<InformationUiPopUp "Energy" #f1c40f>><em>-1 Energy</em>
<</InformationUiPopUp>><</revealtext>>
<div class="BottomUiBarCustom">
<<BottomButton "Decision">><<revealbtn "power" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>>
<<BottomButton "Move" "moveBtn">><<link "↩️ Return">><<goto "UniversityPersonalOffice">><<set $PsychicPower -= 1>><<set $Time++>><<set $Bank += 150>><<set $Energy-->><<set $MakeUniversityClass2++>><</link>><</BottomButton>>
</div><<sound "music" "music.music" true>><<sound "bg" "bg.empty" true>><<passagebg>><<if $Time !== 3>><img src="assets/img/misc/university/universitypersonaloffice.webp"/><<else>><img src="assets/img/misc/university/universitypersonalofficenight.webp"/><</if>><</passagebg>><<set _used = []>><<set _npcCount = 1>><<set _npc1Img = 0>><<set _npc2Img = 0>><<set _npc3Img = 0>><<if _npcCount >= 1>><<set _npc1Img = random(1, 8)>><<set _used.push(_npc1Img)>><</if>><<if _npcCount >= 2>><<set _npc2Img = random(1, 8)>><<for ; _used.includes(_npc2Img) ; >><<set _npc2Img = random(1, 8)>><</for>><<set _used.push(_npc2Img)>><</if>><<if _npcCount >= 3>><<set _npc3Img = random(1, 8)>><<for ; _used.includes(_npc3Img) ; >><<set _npc3Img = random(1, 8)>><</for>><<set _used.push(_npc3Img)>><</if>><<set _img1 = "assets/img/character/npc/G" + _npc1Img + ".jpg">><<set _img2 = "assets/img/character/npc/G" + _npc2Img + ".jpg">><<set _img3 = "assets/img/character/npc/G" + _npc3Img + ".jpg">>
<<InformationUiPopUp>>I called a student into my office after her catastrophic results on the last assignment. She comes in, closes the door, and stays standing with her eyes down.
<</InformationUiPopUp>>
<<TalkMC "You know why you're here?">>
<<TalkRandom "Student" _img1 "My last assignment. I know, it was bad.">>
<<TalkMC "Bad is an understatement. You didn't hand in half the exercises.">>
<<TalkRandom "Student" _img1 "I didn't have time, I had other classes that...">>
<<TalkMC "I didn't ask for an excuse. I asked for an explanation.">>
<<TalkRandom "Student" _img1 "...">>
<<TalkRandom "Student" _img1 "I'm sorry. Really.">>
<<TalkMC "Being sorry doesn't change your grade. What changes it is what you do next.">>
<<InformationUiPopUp>>She keeps her eyes down, giving me no answer.
<</InformationUiPopUp>>
<<revealtext "power">><<InformationUiPopUp "Psychic Power" #7aa2ff>>You decide to use your power.
<em>-1 Psychic Power</em><</InformationUiPopUp>>
<<TalkMC "Listen.">>
<<TalkMC "We're going to start with the basic rules. Here, bad results have consequences. Do you understand that?">>
<<TalkRandom "Student" _img1 "...">>
<<TalkRandom "Student" _img1 "Yes...">>
<<TalkMC "Good. Then come here.">>
<<InformationUiPopUp>>She steps forward slowly, then I position her for her punishment.
<</InformationUiPopUp>>
<<set _random = random(4)>><<if _random == 0>>
<img src="assets/img/events/university/punish/1.webp"/>
<<elseif _random == 1>>
<img src="assets/img/events/university/punish/2.webp"/>
<<elseif _random == 2>>
<img src="assets/img/events/university/punish/3.webp"/>
<<elseif _random == 3>>
<img src="assets/img/events/university/punish/4.webp"/>
<<elseif _random == 4>>
<img src="assets/img/events/university/punish/5.webp"/>
<</if>>
<<TalkRandom "Student" _img1 "I... I'll do better. I promise.">>
<<TalkMC "I know. Because you're going to understand what it costs to work poorly in my class.">>
<<TalkRandom "Student" _img1 "Yes, Sir.">>
<<TalkMC "You can go. And next time, you hand in your complete work.">>
<<InformationUiPopUp>>She leaves without another word, the door closing behind her. The message has been received.
<</InformationUiPopUp>>
<<InformationUiPopUp "Energy" #f1c40f>><em>-1 Energy</em>
<</InformationUiPopUp>><</revealtext>>
<div class="BottomUiBarCustom"><<BottomButton "Decision">><<revealbtn "power" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>>
<<BottomButton "Move" "moveBtn">><<link "↩️ Return">><<goto "UniversityPersonalOffice">><<set $PsychicPower -= 1>><<set $Energy-->><<set $MakeUniversityClass3++>><<set $TravelPerTime++>><</link>><</BottomButton>>
</div><<sound "music" "music.music" true>><<sound "bg" "bg.empty" true>><<passagebg>><<if $Time !== 3>><img src="assets/img/misc/university/universitypersonaloffice.webp"/><<else>><img src="assets/img/misc/university/universitypersonalofficenight.webp"/><</if>><</passagebg>><<set _used = []>><<set _npcCount = 1>><<set _npc1Img = 0>><<set _npc2Img = 0>><<set _npc3Img = 0>><<if _npcCount >= 1>><<set _npc1Img = random(1, 8)>><<set _used.push(_npc1Img)>><</if>><<if _npcCount >= 2>><<set _npc2Img = random(1, 8)>><<for ; _used.includes(_npc2Img) ; >><<set _npc2Img = random(1, 8)>><</for>><<set _used.push(_npc2Img)>><</if>><<if _npcCount >= 3>><<set _npc3Img = random(1, 8)>><<for ; _used.includes(_npc3Img) ; >><<set _npc3Img = random(1, 8)>><</for>><<set _used.push(_npc3Img)>><</if>><<set _img1 = "assets/img/character/npc/G" + _npc1Img + ".jpg">><<set _img2 = "assets/img/character/npc/G" + _npc2Img + ".jpg">><<set _img3 = "assets/img/character/npc/G" + _npc3Img + ".jpg">>
<<InformationUiPopUp>>A student came for an intensive revision session before the exams. She arrives relaxed.
<</InformationUiPopUp>>
<<set _random = random(1)>><<if _random == 0>>
<img src="assets/img/events/university/basic/1.webp"/>
<<elseif _random == 1>>
<img src="assets/img/events/university/basic/2.webp"/>
<</if>>
<<InformationUiPopUp>>Once settled, notes spread across the desk, course open on the screen.
<</InformationUiPopUp>>
<<TalkRandom "Student" _img1 "I really don't get this part, no matter how many times I read it I draw a blank.">>
<<TalkMC "Show me exactly where you're getting stuck.">>
<<TalkRandom "Student" _img1 "There. That whole section.">>
<<TalkMC "We'll redo it together. But first, you're going to explain to me what you did understand, even if it's incomplete.">>
<<TalkRandom "Student" _img1 "I... I think it's about this, but then I lose the thread.">>
<<TalkMC "That's a good start. Now listen to me carefully.">>
<<revealtext "power">><<InformationUiPopUp "Psychic Power" #7aa2ff>>You decide to use your power.
<em>-1 Psychic Power</em><</InformationUiPopUp>>
<<TalkMC "Listen.">>
<<TalkMC "I'm going to help you, but for the work to really pay off, you're going to have to get undressed and suck me off. It's part of the educational process. It'll let you relax completely and be more open to learning.">>
<<InformationUiPopUp>>She nods, then looks up at me and meets my eyes differently.
<</InformationUiPopUp>>
<<TalkRandom "Student" _img1 "Alright, Sir.">>
<<TalkRandom "Student" _img1 "Do you really do this for all your students?">>
<<TalkMC "No. Only for those who are worth it.">>
<<set _random = random(5)>><<if _random == 0>>
<img src="assets/img/events/university/nude/solo/1.webp"/>
<<elseif _random == 1>>
<img src="assets/img/events/university/nude/solo/2.webp"/>
<<elseif _random == 2>>
<img src="assets/img/events/university/nude/solo/3.webp"/>
<<elseif _random == 3>>
<img src="assets/img/events/university/nude/solo/4.webp"/>
<<elseif _random == 4>>
<img src="assets/img/events/university/nude/solo/5.webp"/>
<<elseif _random == 5>>
<img src="assets/img/events/university/nude/solo/6.webp"/>
<</if>>
<<InformationUiPopUp>>Once undressed, she waits for me to pull my trousers down, already ready.
<</InformationUiPopUp>>
<<TalkMC "Show me first what you look like when you relax on your own.">>
<<set _random = random(3)>><<if _random == 0>>
<img src="assets/img/events/university/masturbation/1.webp"/>
<<elseif _random == 1>>
<img src="assets/img/events/university/masturbation/2.webp"/>
<<elseif _random == 2>>
<img src="assets/img/events/university/masturbation/3.webp"/>
<<elseif _random == 3>>
<img src="assets/img/events/university/masturbation/4.webp"/>
<</if>>
<<InformationUiPopUp>>She does it without hesitating, eyes on mine.
<</InformationUiPopUp>>
<<TalkRandom "Student" _img1 "<em>Ah... mmh... yes...</em>">>
<<TalkMC "Good, come here now.">>
<<set _random = random(10)>><<if _random == 0>>
<img src="assets/img/events/university/blowjob/solo/1.webp"/>
<<elseif _random == 1>>
<img src="assets/img/events/university/blowjob/solo/2.webp"/>
<<elseif _random == 2>>
<img src="assets/img/events/university/blowjob/solo/3.webp"/>
<<elseif _random == 3>>
<img src="assets/img/events/university/blowjob/solo/4.webp"/>
<<elseif _random == 4>>
<img src="assets/img/events/university/blowjob/solo/5.webp"/>
<<elseif _random == 5>>
<img src="assets/img/events/university/blowjob/solo/6.webp"/>
<<elseif _random == 6>>
<img src="assets/img/events/university/blowjob/solo/7.webp"/>
<<elseif _random == 7>>
<img src="assets/img/events/university/blowjob/solo/8.webp"/>
<<elseif _random == 8>>
<img src="assets/img/events/university/blowjob/solo/9.webp"/>
<<elseif _random == 9>>
<img src="assets/img/events/university/blowjob/solo/10.webp"/>
<<elseif _random == 10>>
<img src="assets/img/events/university/blowjob/solo/11.webp"/>
<</if>>
<<TalkRandom "Student" _img1 "<em>Glrk... mmh... ghlk...</em>">>
<<TalkMC "Deeper.">>
<<TalkRandom "Student" _img1 "Mm.">>
<<TalkMC "On your knees!">>
<<set _random = random(4)>>
<<if _random == 0>>
<img src="assets/img/events/university/cum/1.webp"/>
<<elseif _random == 1>>
<img src="assets/img/events/university/cum/2.webp"/>
<<elseif _random == 2>>
<img src="assets/img/events/university/cum/3.webp"/>
<<elseif _random == 3>>
<img src="assets/img/events/university/cum/4.webp"/>
<<elseif _random == 4>>
<img src="assets/img/events/university/cum/5.webp"/>
<</if>>
<<InformationUiPopUp>>She stays still for a moment, then wipes herself and gets dressed without rushing, looking completely at ease, relaxed.
<</InformationUiPopUp>>
<<TalkRandom "Student" _img1 "You were right, Sir, it really does work!">>
<<TalkRandom "Student" _img1 "I feel... so much better.">>
<<TalkMC "Good, let's start the revision now, you'll see, you'll understand right away.">>
<<InformationUiPopUp>>After several minutes helping and explaining, she picks up her things and leaves, the door closing softly behind her.
<</InformationUiPopUp>>
<<InformationUiPopUp "Energy" #f1c40f>><em>-1 Energy</em>
<</InformationUiPopUp>><</revealtext>>
<div class="BottomUiBarCustom"><<BottomButton "Decision">><<revealbtn "power" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>>
<<BottomButton "Move" "moveBtn">><<link "↩️ Return">><<goto "UniversityPersonalOffice">><<set $PsychicPower -= 1>><<set $Time++>><<set $Energy-->><<set $MakeUniversityClass4++>><</link>><</BottomButton>>
</div><<sound "music" "music.music" true>><<sound "bg" "bg.empty" true>><<passagebg>><<if $Time !== 3>><img src="assets/img/misc/university/universitypersonaloffice.webp"/><<else>><img src="assets/img/misc/university/universitypersonalofficenight.webp"/><</if>><</passagebg>><<set _used = []>><<set _npcCount = 3>><<set _npc1Img = 0>><<set _npc2Img = 0>><<set _npc3Img = 0>><<if _npcCount >= 1>><<set _npc1Img = random(1, 8)>><<set _used.push(_npc1Img)>><</if>><<if _npcCount >= 2>><<set _npc2Img = random(1, 8)>><<for ; _used.includes(_npc2Img) ; >><<set _npc2Img = random(1, 8)>><</for>><<set _used.push(_npc2Img)>><</if>><<if _npcCount >= 3>><<set _npc3Img = random(1, 8)>><<for ; _used.includes(_npc3Img) ; >><<set _npc3Img = random(1, 8)>><</for>><<set _used.push(_npc3Img)>><</if>><<set _img1 = "assets/img/character/npc/G" + _npc1Img + ".jpg">><<set _img2 = "assets/img/character/npc/G" + _npc2Img + ".jpg">><<set _img3 = "assets/img/character/npc/G" + _npc3Img + ".jpg">>
<<InformationUiPopUp>>Three students came together for a group revision session before the exams.
<</InformationUiPopUp>>
<<TalkRandom "Student" _img1 "We all got stuck on the same chapter, that's why we came together.">>
<<TalkMC "No problem, we'll go through it methodically. But first, you know what needs to be done.">>
<<TalkRandom "Student" _img1 "Of course.">>
<<TalkRandom "Student" _img2 "Yes.">>
<<TalkRandom "Student" _img3 "But Sir... there... there are several of us here.">>
<<revealtext "power">><<InformationUiPopUp "Psychic Power" #7aa2ff>>You decide to use your power.
<em>-1 Psychic Power</em><</InformationUiPopUp>>
<<TalkMC "Listen.">>
<<TalkMC "You'll have no problem being undressed, no modesty whatsoever, doing this together or in front of others. It's part of the educational process, there's nothing more normal.">>
<<InformationUiPopUp>>They stay frozen for a moment, then start undressing, laughing and getting excited about the session ahead.
<</InformationUiPopUp>>
<<set _random = random(2)>><<if _random == 0>>
<img src="assets/img/events/university/nude/group/1.webp"/>
<<elseif _random == 1>>
<img src="assets/img/events/university/nude/group/2.webp"/>
<<elseif _random == 2>>
<img src="assets/img/events/university/nude/group/3.webp"/>
<</if>>
<<TalkMC "Good. Now come here.">>
<<set _random = random(4)>><<if _random == 0>>
<img src="assets/img/events/university/blowjob/group/1.webp"/>
<<elseif _random == 1>>
<img src="assets/img/events/university/blowjob/group/2.webp"/>
<<elseif _random == 2>>
<img src="assets/img/events/university/blowjob/group/3.webp"/>
<<elseif _random == 3>>
<img src="assets/img/events/university/blowjob/group/4.webp"/>
<<elseif _random == 4>>
<img src="assets/img/events/university/blowjob/group/5.webp"/>
<</if>>
<<TalkRandom "Student" _img2 "<em>Glrk... mmh...</em>">>
<<TalkMC "One at a time. Nobody's in a rush.">>
<<TalkRandom "Student" _img1 "<em>Mmh... ghlk...</em>">>
<<TalkMC "On your knees, all of you.">>
<<set _random = random(4)>>
<<if _random == 0>>
<img src="assets/img/events/university/cum/1.webp"/>
<<elseif _random == 1>>
<img src="assets/img/events/university/cum/2.webp"/>
<<elseif _random == 2>>
<img src="assets/img/events/university/cum/3.webp"/>
<<elseif _random == 3>>
<img src="assets/img/events/university/cum/4.webp"/>
<<elseif _random == 4>>
<img src="assets/img/events/university/cum/5.webp"/>
<</if>>
<<InformationUiPopUp>>They look at each other, then look at me, with a satisfied smile.
<</InformationUiPopUp>>
<<TalkMC "Let's start the revision now.">>
<<InformationUiPopUp>>After several minutes, they pick up their things and leave, the door closing softly behind them.
<</InformationUiPopUp>>
<<InformationUiPopUp "Energy" #f1c40f>><em>-1 Energy</em>
<</InformationUiPopUp>><</revealtext>>
<div class="BottomUiBarCustom"><<BottomButton "Decision">><<revealbtn "power" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>>
<<BottomButton "Move" "moveBtn">><<link "↩️ Return">><<goto "UniversityPersonalOffice">><<set $PsychicPower -= 1>><<set $Time++>><<set $Energy-->><<set $MakeUniversityClass5++>><</link>><</BottomButton>>
</div><<sound "music" "music.music" true>><<sound "bg" "bg.empty" true>><<passagebg>><<if $Time !== 3>><img src="assets/img/misc/university/universitypersonaloffice.webp"/><<else>><img src="assets/img/misc/university/universitypersonalofficenight.webp"/><</if>><</passagebg>><<set _used = []>><<set _npcCount = 1>><<set _npc1Img = 0>><<set _npc2Img = 0>><<set _npc3Img = 0>><<if _npcCount >= 1>><<set _npc1Img = random(1, 8)>><<set _used.push(_npc1Img)>><</if>><<if _npcCount >= 2>><<set _npc2Img = random(1, 8)>><<for ; _used.includes(_npc2Img) ; >><<set _npc2Img = random(1, 8)>><</for>><<set _used.push(_npc2Img)>><</if>><<if _npcCount >= 3>><<set _npc3Img = random(1, 8)>><<for ; _used.includes(_npc3Img) ; >><<set _npc3Img = random(1, 8)>><</for>><<set _used.push(_npc3Img)>><</if>><<set _img1 = "assets/img/character/npc/G" + _npc1Img + ".jpg">><<set _img2 = "assets/img/character/npc/G" + _npc2Img + ".jpg">><<set _img3 = "assets/img/character/npc/G" + _npc3Img + ".jpg">>
<<InformationUiPopUp>>A student came for what I presented to her as a private practical anatomy class. She's a little wary, but curious.
<</InformationUiPopUp>>
<<TalkMC "Anatomy can't really be learned from a diagram. You have to understand the body in practice.">>
<<TalkRandom "Student" _img1 "That's... a fairly original method.">>
<<TalkMC "Original methods get the best results. You're here to learn, aren't you?">>
<<TalkRandom "Student" _img1 "Yes, but...">>
<<revealtext "power">><<InformationUiPopUp "Psychic Power" #7aa2ff>>You decide to use your power.
<em>-1 Psychic Power</em><</InformationUiPopUp>>
<<TalkMC "Listen.">>
<<TalkMC "You're going to love this class. By the end you'll feel enormous pleasure, a real sense of freedom, and the feeling of having learned something new.">>
<<TalkRandom "Student" _img1 "...">>
<<TalkRandom "Student" _img1 "You're right, Sir.">>
<<TalkMC "Then let's begin. Take your clothes off.">>
<<set _random = random(5)>><<if _random == 0>>
<img src="assets/img/events/university/nude/solo/1.webp"/>
<<elseif _random == 1>>
<img src="assets/img/events/university/nude/solo/2.webp"/>
<<elseif _random == 2>>
<img src="assets/img/events/university/nude/solo/3.webp"/>
<<elseif _random == 3>>
<img src="assets/img/events/university/nude/solo/4.webp"/>
<<elseif _random == 4>>
<img src="assets/img/events/university/nude/solo/5.webp"/>
<<elseif _random == 5>>
<img src="assets/img/events/university/nude/solo/6.webp"/>
<</if>>
<<TalkMC "Good. We'll start with a general observation.">>
<<TalkRandom "Student" _img1 "You really are looking at me like a study subject.">>
<<TalkMC "That's exactly what you are right now.">>
<<TalkMC "The practical part starts now.">>
<<set _random = random(7)>><<if _random == 0>>
<img src="assets/img/events/university/fuck/pussy/1.webp"/>
<<elseif _random == 1>>
<img src="assets/img/events/university/fuck/pussy/2.webp"/>
<<elseif _random == 2>>
<img src="assets/img/events/university/fuck/pussy/3.webp"/>
<<elseif _random == 3>>
<img src="assets/img/events/university/fuck/pussy/4.webp"/>
<<elseif _random == 4>>
<img src="assets/img/events/university/fuck/pussy/5.webp"/>
<<elseif _random == 5>>
<img src="assets/img/events/university/fuck/pussy/6.webp"/>
<<elseif _random == 6>>
<img src="assets/img/events/university/fuck/pussy/7.webp"/>
<<elseif _random == 7>>
<img src="assets/img/events/university/fuck/pussy/8.webp"/>
<</if>>
<<TalkRandom "Student" _img1 "<em>Ah... mmh... yes...</em>">>
<<TalkRandom "Student" _img1 "Oh...">>
<<TalkMC "Stay still. This is a lesson.">>
<<TalkRandom "Student" _img1 "Ah... mmh... yes...">>
<<TalkMC "We're changing position for the next part of the class.">>
<<set _random = random(8)>><<if _random == 0>>
<img src="assets/img/events/university/fuck/anal/1.webp"/>
<<elseif _random == 1>>
<img src="assets/img/events/university/fuck/anal/2.webp"/>
<<elseif _random == 2>>
<img src="assets/img/events/university/fuck/anal/3.webp"/>
<<elseif _random == 3>>
<img src="assets/img/events/university/fuck/anal/4.webp"/>
<<elseif _random == 4>>
<img src="assets/img/events/university/fuck/anal/5.webp"/>
<<elseif _random == 5>>
<img src="assets/img/events/university/fuck/anal/6.webp"/>
<<elseif _random == 6>>
<img src="assets/img/events/university/fuck/anal/7.webp"/>
<<elseif _random == 7>>
<img src="assets/img/events/university/fuck/anal/8.webp"/>
<<elseif _random == 8>>
<img src="assets/img/events/university/fuck/anal/9.webp"/>
<</if>>
<<TalkRandom "Student" _img1 "<em>Ah... fuck... more...</em>">>
<<TalkRandom "Student" _img1 "Is... is this in the curriculum?">>
<<TalkMC "Full anatomy.">>
<<TalkMC "The lesson ends here. On your knees, now!">>
<<set _random = random(4)>>
<<if _random == 0>>
<img src="assets/img/events/university/cum/1.webp"/>
<<elseif _random == 1>>
<img src="assets/img/events/university/cum/2.webp"/>
<<elseif _random == 2>>
<img src="assets/img/events/university/cum/3.webp"/>
<<elseif _random == 3>>
<img src="assets/img/events/university/cum/4.webp"/>
<<elseif _random == 4>>
<img src="assets/img/events/university/cum/5.webp"/>
<</if>>
<<InformationUiPopUp>>After a moment, she gets up, looking light, relaxed.
<</InformationUiPopUp>>
<<TalkRandom "Student" _img1 "That was really great, Sir! Can we do it again?">>
<<TalkMC "Only for students who deserve it. You can get dressed.">>
<<InformationUiPopUp "Energy" #f1c40f>><em>-1 Energy</em>
<</InformationUiPopUp>><</revealtext>>
<div class="BottomUiBarCustom"><<BottomButton "Decision">><<revealbtn "power" "🧠 Use power" "moveBtn">><<UsePsychicPower>><</revealbtn>><</BottomButton>>
<<BottomButton "Move" "moveBtn">><<link "↩️ Return">><<goto "UniversityPersonalOffice">><<set $PsychicPower -= 1>><<set $Time++>><<set $Energy-->><<set $MakeUniversityClass6++>><</link>><</BottomButton>>
</div><<sound "music" "music.music" true>><<sound "bg" "bg.empty" true>><<passagebg>><<if $Time !== 3>><img src="assets/img/misc/university/universitypersonaloffice.webp"/><<else>><img src="assets/img/misc/university/universitypersonalofficenight.webp"/><</if>><</passagebg>><<set _used = []>><<set _npcCount = 3>><<set _npc1Img = 0>><<set _npc2Img = 0>><<set _npc3Img = 0>><<if _npcCount >= 1>><<set _npc1Img = random(1, 8)>><<set _used.push(_npc1Img)>><</if>><<if _npcCount >= 2>><<set _npc2Img = random(1, 8)>><<for ; _used.includes(_npc2Img) ; >><<set _npc2Img = random(1, 8)>><</for>><<set _used.push(_npc2Img)>><</if>><<if _npcCount >= 3>><<set _npc3Img = random(1, 8)>><<for ; _used.includes(_npc3Img) ; >><<set _npc3Img = random(1, 8)>><</for>><<set _used.push(_npc3Img)>><</if>><<set _img1 = "assets/img/character/npc/G" + _npc1Img + ".jpg">><<set _img2 = "assets/img/character/npc/G" + _npc2Img + ".jpg">><<set _img3 = "assets/img/character/npc/G" + _npc3Img + ".jpg">>
<<InformationUiPopUp>>Several students came for the group practical anatomy class. They know what to expect, or at least they think they do.
<</InformationUiPopUp>>
<<TalkMC "You already know the routine, so go ahead, everyone undress.">>
<<InformationUiPopUp>>They comply without the slightest hesitation.
<</InformationUiPopUp>>
<<set _random = random(2)>><<if _random == 0>>
<img src="assets/img/events/university/nude/group/1.webp"/>
<<elseif _random == 1>>
<img src="assets/img/events/university/nude/group/2.webp"/>
<<elseif _random == 2>>
<img src="assets/img/events/university/nude/group/3.webp"/>
<</if>>
<<TalkMC "This class is different from the others. Here we learn through direct experience. Is everyone ready?">>
<<TalkRandom "Student" _img1 "Yes, Sir!">>
<<TalkRandom "Student" _img2 "Yes!">>
<<TalkMC "The first part of the class focuses on the body's response to contact. Let's begin.">>
<<set _random = random(4)>><<if _random == 0>>
<img src="assets/img/events/university/fuck/group/1.webp"/>
<<elseif _random == 1>>
<img src="assets/img/events/university/fuck/group/2.webp"/>
<<elseif _random == 2>>
<img src="assets/img/events/university/fuck/group/3.webp"/>
<<elseif _random == 3>>
<img src="assets/img/events/university/fuck/group/4.webp"/>
<<elseif _random == 4>>
<img src="assets/img/events/university/fuck/group/5.webp"/>
<</if>>
<<TalkRandom "Student" _img3 "<em>Ah... mmh... yes...</em>">>
<<TalkRandom "Student" _img1 "<em>Ah... fuck... more...</em>">>
<<TalkMC "Stay focused. We're in class.">>
<<TalkRandom "Student" _img1 "It's hard to focus, it feels so good, Sir.">>
<<TalkMC "That's precisely the exercise.">>
<<TalkRandom "Student" _img3 "Ah... mmh...">>
<<TalkMC "Class over. All of you on your knees.">>
<<set _random = random(4)>>
<<if _random == 0>>
<img src="assets/img/events/university/cum/1.webp"/>
<<elseif _random == 1>>
<img src="assets/img/events/university/cum/2.webp"/>
<<elseif _random == 2>>
<img src="assets/img/events/university/cum/3.webp"/>
<<elseif _random == 3>>
<img src="assets/img/events/university/cum/4.webp"/>
<<elseif _random == 4>>
<img src="assets/img/events/university/cum/5.webp"/>
<</if>>
<<InformationUiPopUp>>They stay there for a moment, then get up and get dressed unhurriedly, happy, exchanging knowing looks.
<</InformationUiPopUp>>
<<TalkRandom "Student" _img2 "Will we be back for the next class?">>
<<TalkMC "If you remembered the lesson, yes.">>
<<InformationUiPopUp>>They leave one by one. The room empties.
<</InformationUiPopUp>>
<<InformationUiPopUp "Energy" #f1c40f>><em>-1 Energy</em>
<</InformationUiPopUp>>
<div class="BottomUiBarCustom">
<<BottomButton "Move">><<link "↩️ Return">><<goto "UniversityPersonalOffice">><<set $Time++>><<set $Energy-->><</link>><</BottomButton>>
</div><<sound "music" "music.music" true>><<passagebg>><<sound "bg" "bg.city" true>><img src="assets/img/misc/city/cityhall/cityhall.webp"/><</passagebg>>
<<InformationUiPopUp>>Outside the city hall. I am about to go in when two men in suits step out through a side door, stopping just under the porch. They speak in low voices, but in the outer corridor the sound carries. I slow down.
<</InformationUiPopUp>>
<<TalkRandom "Strange Man" "assets/img/character/npc/b1.jpg" "The file is still in her archives. She hasn't passed it to the council yet.">>
<<TalkRandom "Strange Man" "assets/img/character/npc/b4.jpg" "You're sure? Because if she uses it before the next meeting, we're finished.">>
<<TalkRandom "Strange Man" "assets/img/character/npc/b1.jpg" "I'm sure. My source is inside the building. The 2017 geological survey, GE-2017-114, is sitting in her environmental archives. She doesn't know yet what it means for the Financial District project.">>
<<TalkRandom "Strange Man" "assets/img/character/npc/b4.jpg" "And if she figures it out?">>
<<TalkRandom "Strange Man" "assets/img/character/npc/b1.jpg" "Then she can block the entire phase two of the project. That costs us two years of delays and tens of millions. We need to get that file before she makes the connection.">>
<<TalkRandom "Strange Man" "assets/img/character/npc/b4.jpg" "How do you plan to do that without her noticing?">>
<<TalkRandom "Strange Man" "assets/img/character/npc/b1.jpg" "We have someone who can access the archives tonight. But we need to move fast, before she calls in her infrastructure team.">>
<<TalkRandom "Strange Man" "assets/img/character/npc/b4.jpg" "And if it leads back to us?">>
<<TalkRandom "Strange Man" "assets/img/character/npc/b1.jpg" "It won't. That's exactly why we're not going through official channels.">>
<<InformationUiPopUp>>They resume walking and move away without having noticed me. I stay still for a moment. The GE-2017-114 survey. The environmental archives. The Financial District project. This could be very useful.
<</InformationUiPopUp>>
<div class="BottomUiBarCustom">
<<BottomButton "Move">><<link "➡️ Interesting...">><<goto "CityHall">><<set $MayorStoryInfo1 = true>><</link>><</BottomButton>>
</div><<sound "music" "music.music" true>><<sound "bg" "bg.empty" true>><<passagebg>><<if $Time !== 3>><img src="assets/img/misc/oldtown/traphouse/traphouse.webp"/><<else>><img src="assets/img/misc/oldtown/traphouse/traphousenight.webp"/><</if>><</passagebg>>
<<InformationUiPopUp>>The TrapHouse. W. is sitting in his usual corner, half slumped on the couch, a can in his hand. He sees me coming and lifts his chin in greeting.
<</InformationUiPopUp>>
<<TalkRandom "W. <em>(Dealer)</em>" "assets/img/character/npc/b3.jpg" "Well, well. What brings you here?">>
<<TalkMC "I need something.">>
<<TalkRandom "W. <em>(Dealer)</em>" "assets/img/character/npc/b3.jpg" "Yeah, everybody needs something. Be more specific.">>
<<TalkMC "Equipment. To get into somewhere quietly.">>
<<TalkRandom "W. <em>(Dealer)</em>" "assets/img/character/npc/b3.jpg" "Get into somewhere?">>
<<TalkMC "Yeah.">>
<<TalkRandom "W. <em>(Dealer)</em>" "assets/img/character/npc/b3.jpg" "Where?">>
<<TalkMC "What does it matter to you?">>
<<TalkRandom "W. <em>(Dealer)</em>" "assets/img/character/npc/b3.jpg" "It matters a lot, brother. A warehouse is not the same thing as a police station.">>
<<TalkMC "It's neither. Don't worry about it.">>
<<TalkRandom "W. <em>(Dealer)</em>" "assets/img/character/npc/b3.jpg" "And who's it for?">>
<<TalkMC "Nobody you know.">>
<<TalkRandom "W. <em>(Dealer)</em>" "assets/img/character/npc/b3.jpg" "You don't answer anything I ask you, you know that?">>
<<TalkMC "I'm just asking if you've got what I need or not.">>
<<InformationUiPopUp>>He looks at me for a long moment, spinning the can between his hands. Then he exhales through his nose, a kind of half-laugh.
<</InformationUiPopUp>>
<<TalkRandom "W. <em>(Dealer)</em>" "assets/img/character/npc/b3.jpg" "I don't like people who ask me questions and don't answer mine.">>
<<TalkMC "I know. But do you have what I need?">>
<<TalkRandom "W. <em>(Dealer)</em>" "assets/img/character/npc/b3.jpg" "...">>
<<TalkRandom "W. <em>(Dealer)</em>" "assets/img/character/npc/b3.jpg" "Maybe. But nothing's free here. <strong>$500</strong> cash. And I don't want to know what you're doing with it.">>
<<TalkMC "$500?">>
<<TalkRandom "W. <em>(Dealer)</em>" "assets/img/character/npc/b3.jpg" "Cash. No transfer, no fronting. Cash now, equipment now. Otherwise you walk out empty-handed.">>
<<InformationUiPopUp>>He stands up and holds out his hand, waiting.
<</InformationUiPopUp>>
<<TalkRandom "W. <em>(Dealer)</em>" "assets/img/character/npc/b3.jpg" "So? Do we have a deal or not?">>
<div class="BottomUiBarCustom">
<<BottomButton "Action">><<if $Money >= 500>><<link "💵 Pay $500">><<goto "TrapHouse">><<set $MayorStoryInfo2 = true>><<set $Money -= 500>><</link>><<else>><<link "🔒 You don't have enough money on you">><</link>><</if>><</BottomButton>>
<<BottomButton "Move">><<link "❌ Leave">><<goto "TrapHouse">><</link>><</BottomButton>>
</div><<set $ShowTopUiBar = false>><<set $ShowBottomUiBar = false>><<sound "music" "music.music" true>><div id="hb-app"><div id="hb-hdr"><div id="hb-hdr-l"><div id="hb-lvlbadge">Floor <span id="hb-lvlnum">1</span> of 3</div><div id="hb-ttl">City Hall — Archives</div><div id="hb-sub" id="hb-sub">Reach the staircase undetected.</div></div><button id="hb-abandon">🚪 Abandon</button></div><div id="hb-bar"><span id="hb-turn">Turn 1</span><span class="hbs">·</span><span id="hb-ap">AP 3/3</span><span class="hbs">·</span><span id="hb-msg">End Turn first to study the guards.</span></div><div id="hb-main"><div id="hb-gw"><div id="hb-grid"></div></div><div id="hb-side"><div class="hb-sb"><div class="hb-sh">Legend</div><div class="hbl"><span>🕵️</span>You</div><div class="hbl"><span>👤</span>Hidden (1 turn)</div><div class="hbl"><span>📦</span>Cover — always safe</div><div class="hbl"><span>👮↓</span>Guard + facing</div><div class="hbl"><span>😴</span>Distracted</div><div class="hbl"><span class="hb-rsq"></span>Guard vision</div><div class="hbl"><span class="hb-gsq"></span>Move available</div><div class="hbl"><span>🪜</span>Staircase — next floor</div><div class="hbl"><span>📁</span>Archives — goal</div></div><div class="hb-sb"><div class="hb-sh">Actions</div><div class="hbh"><b>Move</b> · green cell · 1 AP</div><div class="hbh"><b>Hide</b> · invisible 1 turn · 1 AP</div><div class="hbh"><b>Distract</b> · stun guard 2 turns · 2 AP</div><div class="hbh"><b>End Turn</b> · guards move, AP resets</div><div class="hbh" style="margin-top:6px;color:rgba(255,255,255,.55);">Guards see 3 cells forward + 1 cell each side. 📦 cover blocks vision.</div></div><div id="hb-act-d"><button id="hb-bh">👤 Hide</button><button id="hb-bd">📢 Distract</button><button id="hb-be">⏭ End Turn</button><button id="hb-br" style="display:none">↩ Retry</button></div></div></div><div id="hb-act-m"><button id="hb-bhm">👤</button><button id="hb-bdm">📢</button><button id="hb-bem">⏭</button><button id="hb-brm" style="display:none">↩</button></div></div>
<style>
*{box-sizing:border-box;}
#hb-app{position:fixed;top:0;left:0;right:0;bottom:0;background:#0b0d11;display:flex;flex-direction:column;overflow:hidden;z-index:10;color:#edf0f7;font-family:inherit;}
#hb-hdr{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:10px 18px;border-bottom:1px solid rgba(255,255,255,.08);background:rgba(255,255,255,.02);flex-shrink:0;}
#hb-hdr-l{display:flex;flex-direction:column;gap:2px;min-width:0;}
#hb-lvlbadge{font-size:calc(12px + var(--font-boost,0px));font-weight:800;letter-spacing:.10em;text-transform:uppercase;color:rgba(230,87,99,.80);}
#hb-ttl{font-size:calc(16px + var(--font-boost,0px));font-weight:900;color:#fff;line-height:1.2;}
#hb-sub{font-size:calc(14px + var(--font-boost,0px));font-weight:500;color:rgba(255,255,255,.42);line-height:1.4;}
#hb-abandon{padding:8px 16px;border-radius:8px;border:1px solid rgba(255,255,255,.14);background:rgba(255,255,255,.04);color:rgba(255,255,255,.65);font-size:calc(14px + var(--font-boost,0px));font-weight:700;cursor:pointer;font-family:inherit;white-space:nowrap;flex-shrink:0;transition:all .15s;}
#hb-abandon:hover{background:rgba(255,255,255,.10);color:#fff;}
#hb-bar{display:flex;align-items:center;gap:9px;padding:7px 18px;background:rgba(0,0,0,.40);border-bottom:1px solid rgba(255,255,255,.06);flex-shrink:0;flex-wrap:wrap;}
#hb-turn,#hb-ap{font-size:calc(14px + var(--font-boost,0px));font-weight:800;color:rgba(255,255,255,.90);white-space:nowrap;}
.hbs{color:rgba(255,255,255,.18);font-size:calc(14px + var(--font-boost,0px));}
#hb-msg{flex:1;font-size:calc(14px + var(--font-boost,0px));color:rgba(255,255,255,.55);font-weight:500;min-width:0;}
#hb-main{display:flex;flex:1;overflow:hidden;min-height:0;}
#hb-gw{flex:1;display:flex;align-items:center;justify-content:center;overflow:hidden;padding:12px;background:rgba(0,0,0,.22);}
#hb-grid{display:grid;gap:3px;}
.hb-cell{display:flex;align-items:center;justify-content:center;cursor:pointer;transition:background .10s,transform .10s;user-select:none;position:relative;}
.hb-wall{background:rgba(255,255,255,.14);cursor:default;}
.hb-wall::after{content:'';position:absolute;inset:0;background:repeating-linear-gradient(45deg,rgba(255,255,255,.04) 0,rgba(255,255,255,.04) 2px,transparent 2px,transparent 6px);}
.hb-floor{background:rgba(255,255,255,.04);}
.hb-floor:hover{background:rgba(255,255,255,.09);}
.hb-vis{box-shadow:inset 0 0 0 200px rgba(230,87,99,.22)!important;}
.hb-mv{background:rgba(62,207,142,.16);border:1px solid rgba(62,207,142,.38);}
.hb-mv:hover{background:rgba(62,207,142,.30);transform:scale(1.08);}
.hb-p{background:rgba(100,140,255,.24);border:1px solid rgba(100,140,255,.52);}
.hb-ph{background:rgba(100,140,255,.07);border:1px dashed rgba(100,140,255,.30);}
.hb-g{background:rgba(180,35,45,.40);border:1px solid rgba(230,87,99,.65);}
.hb-gd{background:rgba(170,140,15,.22);border:1px solid rgba(230,195,87,.48);}
.hb-stair{background:rgba(80,160,255,.18);border:1px solid rgba(80,160,255,.50);}
.hb-arch{background:rgba(200,160,20,.22);border:1px solid rgba(230,195,87,.65);}
.hb-cover{background:rgba(55,75,55,.50);border:1px solid rgba(80,140,80,.38);}
.hb-cover:hover{background:rgba(55,75,55,.70);}
.hb-dt{background:rgba(230,195,87,.30)!important;border:2px solid rgba(230,195,87,.72)!important;cursor:crosshair;}
.hb-gin{display:flex;flex-direction:column;align-items:center;line-height:1;}
.hb-gdir{opacity:.85;margin-top:-2px;}
#hb-side{width:208px;flex-shrink:0;border-left:1px solid rgba(255,255,255,.07);background:rgba(255,255,255,.01);display:flex;flex-direction:column;overflow-y:auto;}
.hb-sb{padding:13px;border-bottom:1px solid rgba(255,255,255,.06);}
.hb-sh{font-size:calc(14px + var(--font-boost,0px));font-weight:900;letter-spacing:.08em;text-transform:uppercase;color:rgba(255,255,255,.28);margin-bottom:9px;}
.hbl{display:flex;align-items:center;gap:8px;font-size:calc(14px + var(--font-boost,0px));color:rgba(255,255,255,.58);font-weight:500;margin-bottom:5px;}
.hbl span:first-child{flex-shrink:0;}
.hb-rsq{display:inline-block;width:14px;height:14px;border-radius:3px;background:rgba(230,87,99,.28);border:1px solid rgba(230,87,99,.55);}
.hb-gsq{display:inline-block;width:14px;height:14px;border-radius:3px;background:rgba(62,207,142,.22);border:1px solid rgba(62,207,142,.45);}
.hbh{font-size:calc(14px + var(--font-boost,0px));color:rgba(255,255,255,.38);font-weight:500;line-height:1.55;margin-bottom:3px;}
.hbh b{color:rgba(255,255,255,.72);font-weight:700;}
#hb-act-d{padding:11px;display:flex;flex-direction:column;gap:7px;}
#hb-act-d button{width:100%;padding:10px 12px;border-radius:8px;border:1px solid rgba(255,255,255,.11);background:rgba(255,255,255,.05);color:rgba(255,255,255,.85);font-size:calc(14px + var(--font-boost,0px));font-weight:700;cursor:pointer;transition:all .15s;font-family:inherit;text-align:left;}
#hb-act-d button:hover:not(:disabled){background:rgba(255,255,255,.10);border-color:rgba(255,255,255,.22);}
#hb-act-d button:disabled{opacity:.18;cursor:not-allowed;}
#hb-be{background:rgba(230,87,99,.10)!important;border-color:rgba(230,87,99,.24)!important;color:rgba(230,87,99,.90)!important;}
#hb-be:hover:not(:disabled){background:rgba(230,87,99,.20)!important;}
.hb-on{background:rgba(62,207,142,.14)!important;border-color:rgba(62,207,142,.40)!important;color:rgba(62,207,142,.90)!important;}
#hb-act-m{display:none;flex-shrink:0;padding:7px;gap:5px;border-top:1px solid rgba(255,255,255,.08);background:rgba(0,0,0,.35);}
#hb-act-m button{flex:1;padding:11px 4px;border-radius:8px;border:1px solid rgba(255,255,255,.11);background:rgba(255,255,255,.05);color:rgba(255,255,255,.85);font-size:calc(14px + var(--font-boost,0px));font-weight:700;cursor:pointer;font-family:inherit;transition:all .15s;text-align:center;}
#hb-act-m button:hover:not(:disabled){background:rgba(255,255,255,.10);}
#hb-act-m button:disabled{opacity:.18;cursor:not-allowed;}
#hb-bem{background:rgba(230,87,99,.10)!important;border-color:rgba(230,87,99,.24)!important;color:rgba(230,87,99,.90)!important;}
.hb-on-m{background:rgba(62,207,142,.14)!important;border-color:rgba(62,207,142,.40)!important;color:rgba(62,207,142,.90)!important;}
.hb-overlay{position:absolute;inset:0;background:rgba(11,13,17,.92);display:flex;align-items:center;justify-content:center;z-index:50;}
.hb-ov-box{background:#161921;border:1px solid rgba(255,255,255,.12);border-radius:14px;padding:36px 44px;text-align:center;display:flex;flex-direction:column;align-items:center;gap:12px;max-width:340px;}
.hb-ov-ic{font-size:calc(36px + var(--font-boost,0px));margin-bottom:4px;}
.hb-ov-t{font-size:calc(18px + var(--font-boost,0px));font-weight:900;color:#fff;}
.hb-ov-s{font-size:calc(14px + var(--font-boost,0px));color:rgba(255,255,255,.55);line-height:1.55;font-weight:500;}
@media(max-width:640px){
#hb-side{display:none;}
#hb-act-m{display:flex;}
#hb-sub{display:none;}
#hb-hdr{padding:9px 14px;}
#hb-bar{padding:6px 14px;}
#hb-gw{padding:8px;}
}
</style>
<<script>>
(function(){
var LEVELS=[
{
id:0,title:'Floor 1 — Lobby',subtitle:'Study the guards before moving. Reach the staircase.',
cols:10,rows:7,playerStart:{x:0,y:6},goalTile:4,goalEmoji:'🪜',
startMsg:'End Turn to study guard patterns first.',
map:[
[1,0,0,0,0,0,0,0,0,4],
[0,0,1,0,0,0,0,0,0,0],
[0,0,1,0,0,3,0,0,0,0],
[0,0,0,0,0,0,0,0,1,0],
[1,0,0,0,0,0,0,0,1,0],
[1,0,3,0,0,0,0,0,0,0],
[0,0,0,0,3,0,0,0,0,0]
],
guards:[
{x:3,y:0,path:[{x:3,y:0},{x:4,y:0},{x:5,y:0},{x:6,y:0},{x:7,y:0},{x:8,y:0},{x:8,y:1},{x:7,y:1},{x:6,y:1},{x:5,y:1},{x:4,y:1},{x:3,y:1}],pi:0,dist:0},
{x:9,y:2,path:[{x:9,y:2},{x:9,y:3},{x:9,y:4},{x:9,y:5},{x:9,y:6},{x:8,y:6},{x:7,y:6},{x:7,y:5},{x:8,y:5},{x:9,y:5},{x:9,y:4},{x:9,y:3}],pi:0,dist:0}
]
},
{
id:1,title:'Floor 2 — Office Wing',subtitle:'Three guards patrol intersecting routes. Use cover and timing.',
cols:10,rows:7,playerStart:{x:0,y:6},goalTile:4,goalEmoji:'🪜',
startMsg:'Three guards now. Watch for crossing patrols.',
map:[
[0,0,0,0,0,0,0,0,0,4],
[0,1,0,0,1,0,0,0,0,0],
[0,1,0,3,0,0,0,0,0,0],
[0,0,0,0,0,0,0,0,1,0],
[0,0,0,0,0,0,1,0,1,0],
[0,0,0,0,0,0,1,0,0,0],
[0,0,3,0,0,0,3,0,0,0]
],
guards:[
{x:0,y:0,path:[{x:0,y:0},{x:1,y:0},{x:2,y:0},{x:3,y:0},{x:4,y:0},{x:5,y:0},{x:4,y:0},{x:3,y:0},{x:2,y:0},{x:1,y:0},{x:0,y:0},{x:0,y:1},{x:0,y:2},{x:0,y:3},{x:0,y:2},{x:0,y:1}],pi:0,dist:0},
{x:9,y:1,path:[{x:9,y:1},{x:9,y:2},{x:9,y:3},{x:9,y:4},{x:9,y:5},{x:9,y:6},{x:8,y:6},{x:7,y:6},{x:7,y:5},{x:7,y:4},{x:7,y:3},{x:7,y:2},{x:7,y:1},{x:8,y:1}],pi:0,dist:0},
{x:4,y:5,path:[{x:4,y:5},{x:3,y:5},{x:2,y:5},{x:2,y:4},{x:2,y:3},{x:3,y:3},{x:4,y:3},{x:5,y:3},{x:5,y:4},{x:5,y:5}],pi:0,dist:0}
]
},
{
id:2,title:'Floor 3 — Archives',subtitle:'Four guards. Steal file GE-2017-114. No second chances.',
cols:10,rows:7,playerStart:{x:0,y:6},goalTile:2,goalEmoji:'📁',
startMsg:'Four guards. Use every tool. Reach the archives.',
map:[
[1,0,0,0,0,0,0,0,0,2],
[0,0,0,0,1,0,0,0,1,0],
[0,0,1,0,0,0,0,0,1,0],
[0,0,1,0,0,0,0,0,0,0],
[0,0,0,0,1,0,0,0,0,0],
[0,0,0,0,1,0,0,0,0,0],
[0,0,3,0,0,0,3,0,0,0]
],
guards:[
{x:1,y:0,path:[{x:1,y:0},{x:2,y:0},{x:3,y:0},{x:4,y:0},{x:5,y:0},{x:6,y:0},{x:7,y:0},{x:8,y:0},{x:7,y:0},{x:6,y:0},{x:5,y:0},{x:4,y:0},{x:3,y:0},{x:2,y:0},{x:1,y:0},{x:1,y:1}],pi:0,dist:0},
{x:9,y:1,path:[{x:9,y:1},{x:9,y:2},{x:9,y:3},{x:9,y:4},{x:9,y:5},{x:9,y:6},{x:8,y:6},{x:7,y:6},{x:7,y:5},{x:8,y:5},{x:9,y:5},{x:9,y:4},{x:9,y:3},{x:9,y:2}],pi:0,dist:0},
{x:3,y:2,path:[{x:3,y:2},{x:3,y:3},{x:3,y:4},{x:3,y:5},{x:3,y:6},{x:4,y:6},{x:5,y:6},{x:5,y:5},{x:5,y:4},{x:5,y:3},{x:4,y:3},{x:3,y:3}],pi:0,dist:0},
{x:6,y:1,path:[{x:6,y:1},{x:7,y:1},{x:7,y:2},{x:7,y:3},{x:6,y:3},{x:6,y:2},{x:5,y:2},{x:5,y:1}],pi:0,dist:0}
]
}
];
var currentLevel=0;
var COLS,ROWS,MAP;
var S;
function setLevel(lvl){COLS=LEVELS[lvl].cols;ROWS=LEVELS[lvl].rows;MAP=LEVELS[lvl].map;}
function mkState(lvl){
var L=LEVELS[lvl];
return{
level:lvl,turn:1,ap:3,
player:{x:L.playerStart.x,y:L.playerStart.y},
hidden:false,distractMode:false,
guards:JSON.parse(JSON.stringify(L.guards)),
gameOver:false,win:false,
msg:L.startMsg
};
}
setLevel(0);
S=mkState(0);
function guardVision(g){
if(g.dist>0) return[];
var n=(g.pi+1)%g.path.length;
var nx=g.path[n];
var dx=nx.x-g.x,dy=nx.y-g.y;
if(dx===0&&dy===0) return[];
var sx=dx===0?0:(dx>0?1:-1),sy=dy===0?0:(dy>0?1:-1);
var cells=[];
for(var i=1;i<=3;i++){
var cx=g.x+sx*i,cy=g.y+sy*i;
if(cx<0||cx>=COLS||cy<0||cy>=ROWS) break;
if(MAP[cy][cx]===1) break;
cells.push({x:cx,y:cy});
}
var perp=sx!==0?[{x:g.x,y:g.y-1},{x:g.x,y:g.y+1}]:[{x:g.x-1,y:g.y},{x:g.x+1,y:g.y}];
perp.forEach(function(p){
if(p.x>=0&&p.x<COLS&&p.y>=0&&p.y<ROWS&&MAP[p.y][p.x]!==1) cells.push(p);
});
return cells;
}
function allVisible(){
var v={};
S.guards.forEach(function(g){guardVision(g).forEach(function(c){v[c.x+','+c.y]=true;});});
return v;
}
function detected(){
if(S.hidden) return false;
var px=S.player.x,py=S.player.y;
if(MAP[py][px]===3) return false;
return!!allVisible()[px+','+py];
}
function guardAt(x,y){return S.guards.find(function(g){return g.x===x&&g.y===y;});}
function dirArrow(g){
var n=(g.pi+1)%g.path.length,nx=g.path[n];
var dx=nx.x-g.x,dy=nx.y-g.y;
if(dx>0)return'→';if(dx<0)return'←';if(dy>0)return'↓';if(dy<0)return'↑';return'·';
}
function computeCell(){
var wrap=document.getElementById('hb-gw');
if(!wrap) return 40;
var w=wrap.clientWidth-24,h=wrap.clientHeight-24;
return Math.max(28,Math.min(Math.floor((w-(COLS-1)*3)/COLS),Math.floor((h-(ROWS-1)*3)/ROWS),76));
}
function applySize(){
var cs=computeCell(),g=document.getElementById('hb-grid');
if(!g) return;
g.style.gridTemplateColumns='repeat('+COLS+','+cs+'px)';
g.style.gridTemplateRows='repeat('+ROWS+','+cs+'px)';
var fs=Math.max(14,Math.floor(cs*0.46)),sf=Math.max(9,Math.floor(cs*0.24));
var st=document.getElementById('hb-csz');
if(!st){st=document.createElement('style');st.id='hb-csz';document.head.appendChild(st);}
st.textContent='.hb-cell{font-size:'+fs+'px;border-radius:'+Math.max(4,Math.floor(cs*0.10))+'px;}.hb-gdir{font-size:'+sf+'px;}';
}
function render(){
applySize();
var L=LEVELS[S.level];
document.getElementById('hb-lvlnum').textContent=S.level+1;
document.getElementById('hb-ttl').textContent=L.title;
document.getElementById('hb-sub').textContent=L.subtitle;
var grid=document.getElementById('hb-grid');
if(!grid) return;
grid.innerHTML='';
var px=S.player.x,py=S.player.y,vis=allVisible();
for(var r=0;r<ROWS;r++){
for(var c=0;c<COLS;c++){
var cell=document.createElement('div');
cell.className='hb-cell';
cell.dataset.x=c;cell.dataset.y=r;
var tile=MAP[r][c],isP=(px===c&&py===r),g=guardAt(c,r),isV=!!vis[c+','+r];
if(tile===1){
cell.classList.add('hb-wall');
} else if(tile===2){
cell.classList.add('hb-arch');if(isV) cell.classList.add('hb-vis');
cell.textContent='📁';
} else if(tile===4){
cell.classList.add('hb-stair');if(isV) cell.classList.add('hb-vis');
cell.textContent='🪜';
} else if(tile===3){
cell.classList.add('hb-cover');
if(isP){var pi=document.createElement('span');pi.textContent=S.hidden?'👤':'🕵️';cell.appendChild(pi);}
else cell.textContent='📦';
} else if(g){
cell.classList.add(g.dist>0?'hb-gd':'hb-g');
if(S.distractMode&&!g.dist) cell.classList.add('hb-dt');
var gi=document.createElement('div');gi.className='hb-gin';
var ge=document.createElement('span');ge.textContent=g.dist>0?'😴':'👮';gi.appendChild(ge);
if(!g.dist){var gd=document.createElement('span');gd.className='hb-gdir';gd.textContent=dirArrow(g);gi.appendChild(gd);}
cell.appendChild(gi);
} else if(isP){
cell.classList.add(S.hidden?'hb-ph':'hb-p');
if(isV&&!S.hidden) cell.classList.add('hb-vis');
cell.textContent=S.hidden?'👤':'🕵️';
} else {
cell.classList.add('hb-floor');
if(isV) cell.classList.add('hb-vis');
if(!S.gameOver&&!S.distractMode&&S.ap>0&&!g){
var dxc=Math.abs(c-px),dyc=Math.abs(r-py);
if((dxc===1&&dyc===0)||(dxc===0&&dyc===1)) cell.classList.add('hb-mv');
}
}
cell.addEventListener('click',onCell);
grid.appendChild(cell);
}
}
document.getElementById('hb-turn').textContent='Turn '+S.turn;
document.getElementById('hb-ap').textContent='AP '+S.ap+'/3';
document.getElementById('hb-msg').textContent=S.msg;
syncBtns();
}
function syncBtns(){
var mob=window.innerWidth<=640;
var bh=document.getElementById(mob?'hb-bhm':'hb-bh');
var bd=document.getElementById(mob?'hb-bdm':'hb-bd');
var be=document.getElementById(mob?'hb-bem':'hb-be');
var brD=document.getElementById('hb-br'),brM=document.getElementById('hb-brm');
var isRetry=S.gameOver&&!S.win;
if(bh){bh.disabled=S.ap<1||S.gameOver||S.hidden;bh.classList.toggle(mob?'hb-on-m':'hb-on',S.hidden);}
if(bd){bd.disabled=S.ap<2||S.gameOver;bd.classList.toggle(mob?'hb-on-m':'hb-on',S.distractMode);}
if(be) be.disabled=S.gameOver;
if(brD) brD.style.display=isRetry?'block':'none';
if(brM) brM.style.display=isRetry?'block':'none';
}
function showOverlay(icon,title,sub,dur,cb){
var app=document.getElementById('hb-app');
var ov=document.createElement('div');ov.className='hb-overlay';
ov.innerHTML='<div class="hb-ov-box"><div class="hb-ov-ic">'+icon+'</div><div class="hb-ov-t">'+title+'</div><div class="hb-ov-s">'+sub+'</div></div>';
app.appendChild(ov);
setTimeout(function(){ov.remove();if(cb) cb();},dur);
}
function onCell(e){
var x=parseInt(e.currentTarget.dataset.x),y=parseInt(e.currentTarget.dataset.y);
if(S.gameOver) return;
if(S.distractMode){
var g=guardAt(x,y);S.distractMode=false;
if(g&&!g.dist){g.dist=2;S.ap-=2;S.msg='Guard stunned for 2 turns!';}
else S.msg='No active guard there. Cancelled.';
render();return;
}
var dxc=Math.abs(x-S.player.x),dyc=Math.abs(y-S.player.y);
if(!((dxc===1&&dyc===0)||(dxc===0&&dyc===1))) return;
if(MAP[y][x]===1) return;
if(S.ap<1){S.msg='No AP — end your turn.';render();return;}
if(guardAt(x,y)){S.gameOver=true;S.msg='🚨 Walked straight into a guard!';render();return;}
S.player.x=x;S.player.y=y;S.ap--;S.hidden=false;
var tile=MAP[y][x];
if(tile===LEVELS[S.level].goalTile){
S.win=true;S.gameOver=true;
if(S.level<2){
var nextL=LEVELS[S.level+1];
showOverlay('🪜','Staircase reached!','Advancing to '+nextL.title+'…',2000,function(){
currentLevel++;setLevel(currentLevel);S=mkState(currentLevel);render();
});
} else {
showOverlay('📁','File GE-2017-114 secured.','Extracting from building…',2000,function(){
State.variables.ShowTopUiBar=true;State.variables.ShowBottomUiBar=true;
Engine.play('MayorStory4');
});
}
render();return;
}
if(detected()){S.gameOver=true;S.msg='🚨 Spotted! A guard saw you.';render();return;}
S.msg='';render();
}
function doHide(){
if(S.ap<1||S.gameOver||S.hidden) return;
S.hidden=true;S.ap--;S.msg='Hiding — invisible until you move.';render();
}
function doDist(){
if(S.ap<2||S.gameOver) return;
S.distractMode=!S.distractMode;
S.msg=S.distractMode?'Click a guard to stun them (2 turns).':'Distract cancelled.';render();
}
function doEnd(){
if(S.gameOver) return;
S.guards.forEach(function(g){
if(g.dist>0){g.dist--;return;}
g.pi=(g.pi+1)%g.path.length;
g.x=g.path[g.pi].x;g.y=g.path[g.pi].y;
});
if(guardAt(S.player.x,S.player.y)){S.gameOver=true;S.msg='🚨 A guard walked into you!';render();return;}
if(detected()){S.gameOver=true;S.msg='🚨 Spotted after guards moved!';render();return;}
S.hidden=false;S.distractMode=false;S.turn++;S.ap=3;
S.msg='Turn '+S.turn+' — 3 AP.';render();
}
function doRetry(){setLevel(currentLevel);S=mkState(currentLevel);render();}
setTimeout(function(){
render();
document.getElementById('hb-bh').addEventListener('click',doHide);
document.getElementById('hb-bd').addEventListener('click',doDist);
document.getElementById('hb-be').addEventListener('click',doEnd);
document.getElementById('hb-br').addEventListener('click',doRetry);
document.getElementById('hb-bhm').addEventListener('click',doHide);
document.getElementById('hb-bdm').addEventListener('click',doDist);
document.getElementById('hb-bem').addEventListener('click',doEnd);
document.getElementById('hb-brm').addEventListener('click',doRetry);
document.getElementById('hb-abandon').addEventListener('click',function(){
State.variables.ShowTopUiBar=true;State.variables.ShowBottomUiBar=true;
Engine.play('CityHall');
});
window.addEventListener('resize',applySize);
},10);
})();
<</script>><<set $ShowTopUiBar = true>><<set $ShowBottomUiBar = true>><<sound "music" "music.music" true>><<passagebg>><<sound "bg" "bg.empty" true>><img src="assets/img/story/mayorstory/archives.webp"/><</passagebg>><<InformationUiPopUp>>The town hall archive room. Silent, dimly lit by my flashlight. Rows of metal filing cabinets stretch the full length of the room. I search methodically, drawer after drawer, looking for the environmental records.
<</InformationUiPopUp>>
<<InformationUiPopUp>>Twenty minutes of searching, then I find it, GE-2017-114. I pull it from the cabinet and start skimming through it quickly when I hear a sound. Footsteps in the corridor, the door handle goes down, I don't have time to hide, the door opens.
<</InformationUiPopUp>>
<<TalkRandom "Thief" "assets/img/character/npc/b2.jpg" "What the...">>
<<InformationUiPopUp>>We look at each other, he's masked too. I'm certain he's the guy sent by the two men I heard outside the town hall. He's holding a flashlight in one hand, and in the other something I can't quite make out yet. He looks at the file in my hands.
<</InformationUiPopUp>>
<<TalkRandom "Thief" "assets/img/character/npc/b2.jpg" "So someone else had the same idea.">>
<<TalkMC "Looks like it.">>
<<TalkRandom "Thief" "assets/img/character/npc/b2.jpg" "That file doesn't belong to you.">>
<<TalkMC "Doesn't belong to you either.">>
<<TalkRandom "Thief" "assets/img/character/npc/b2.jpg" "I was hired to retrieve it. Hand it over and I walk out. Simple.">>
<<TalkMC "Not going to happen.">>
<<TalkRandom "Thief" "assets/img/character/npc/b2.jpg" "I was hoping you'd say that.">>
<<InformationUiPopUp>>He sets down his flashlight and moves toward me. Then he raises his arms, and the object in his hand that I couldn't make out becomes clearer before me, a knife, making clear he is ready to fight despite the guards making their rounds through the building.
<</InformationUiPopUp>>
<<InformationUiPopUp "⚠️ Important ⚠️" "#e65763">>It is advised to save here, you can lose the game during this fight!
<</InformationUiPopUp>>
<div class="BottomUiBarCustom">
<<BottomButton "Action">><<link "💥 Fight">><<goto "MayorStory5">><</link>><</BottomButton>>
</div><<set $Fight = {
type: "Thief",
lvl: 50,
playerMax: $HealMax,
playerHP: $Heal,
enemyMax: 120,
enemyHP: 120,
playerBand: 0,
enemyBand: 2,
playerStaMax: 5,
playerSta: 5,
healCD: 0,
log: [],
p: {},
e: {},
enemyDodgeBias: 0.65
}>><<sound "music" "music.fight" true>><<passagebg>><<sound "bg" "bg.empty" true>><img src="assets/img/story/mayorstory/archives.webp"/><</passagebg>><div id="fight-tip" style="display:none;"></div><div class="fight-ui" style="max-width:960px;margin:auto;"><div id="foe-card" class="foes card" style="display:flex;gap:12px;justify-content:space-between;align-items:center;padding:10px;border:1px solid #444;border-radius:10px;margin-bottom:10px;"><div style="width:100%;"><p style="margin:0;"><strong>Enemy:</strong> <span id="foe-type"></span> (Fitness <span id="foe-lvl"></span>) <span id="foe-states" class="states"></span></p><div class="hp-bar-bg" id="foe-barbg"><div id="foe-bar" class="hp-bar"></div><div class="pop-layer" id="foe-pop"></div></div><p style="margin:4px 0 0 0;">HP <span id="foe-hp"></span> / <span id="foe-max"></span> · 🩹 <span id="foe-band"></span></p></div></div><div id="you-card" class="you card" style="display:flex;gap:12px;justify-content:space-between;align-items:center;padding:10px;border:1px solid #444;border-radius:10px;margin-bottom:14px;"><div style="width:100%;"><p style="margin:0;"><strong>You</strong> (Fitness <span id="player-fit"></span>) <span id="you-states" class="states"></span></p><div class="hp-bar-bg" id="you-barbg"><div id="you-bar" class="hp-bar"></div><div class="pop-layer" id="you-pop"></div></div><div class="sta-row"><span class="sta-label">Stamina</span><div class="sta-bg"><div id="you-sta" class="sta-bar"></div></div><span id="you-sta-txt" class="sta-txt"></span></div><p style="margin:4px 0 0 0;">HP <span id="you-hp"></span> / <span id="you-max"></span> · 🩹 <span id="you-band"></span></p></div></div><div id="fight-actions" style="display:flex;gap:10px;flex-wrap:wrap;margin-bottom:10px;"><button id="btn-atk" type="button" data-tip="Standard attack. Deals solid damage based on your Fitness. Cost: 1 stamina.">🥊 Attack</button><button id="btn-heavy" type="button" data-tip="Heavy attack. Deals 2.5x damage based on Fitness, but costs 2 stamina and misses more often.">💥 Heavy</button><button id="btn-guard" type="button" data-tip="Guard. You take 50% less damage this turn. Cost: 0 stamina. Gain: +1 stamina.">🛡️ Guard</button><button id="btn-heal" type="button" data-tip="Heal using a Medkit. Cooldown: every other turn. Cost: 2 stamina. Requires: 1 Medkit.">🩹 Heal</button><button id="btn-finish" type="button" style="display:none;" data-tip="Finisher. Available when enemy HP is 15% or less. Ends the fight instantly. Cost: 1 stamina.">☠️ Finisher</button></div><div id="fight-popups"></div><div id="fight-stage"></div></div><div class="BottomUiBarCustom"><span style="display:contents;" id="fight-actionsbar"></span></div><style>#fight-tip{position:fixed;z-index:99999;display:none;max-width:280px;padding:8px 10px;border:1px solid rgba(255,255,255,.25);border-radius:10px;background:rgba(10,10,10,.92);backdrop-filter:blur(3px);color:#fff;font-size:.9rem;line-height:1.25;pointer-events:none;box-shadow:0 6px 18px rgba(0,0,0,.35);} .fight-ui p{line-height:1.3;} .fight-ui .card{background:rgba(255,255,255,0.03);} #fight-actions button{padding:8px 12px;border:1px solid #666;border-radius:8px;background:transparent;cursor:pointer;color:#fff;} #fight-actions button:hover{background:rgba(255,255,255,0.06);} #fight-actions button:disabled{opacity:.45;cursor:not-allowed;} .hp-bar-bg{position:relative;height:14px;background:#222;border-radius:7px;overflow:hidden;margin-top:6px;} .hp-bar{height:100%;width:100%;transition:width 250ms ease-in-out,background 250ms linear;} .pop-layer{position:absolute;inset:0;pointer-events:none;overflow:visible;} .dmg-pop{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);font-weight:800;opacity:0;animation:popFloat 650ms ease-out forwards;text-shadow:0 1px 0 rgba(0,0,0,.55);} @keyframes popFloat{0%{opacity:0;transform:translate(-50%,-40%) scale(.9);}15%{opacity:1;}100%{opacity:0;transform:translate(-50%,-140%) scale(1.05);}} .hitFlash{animation:hitFlash 220ms ease-out;} @keyframes hitFlash{0%{filter:none;}40%{filter:brightness(1.35);}100%{filter:none;}} .shake{animation:shake 180ms ease-in-out;} @keyframes shake{0%{transform:translateX(0);}25%{transform:translateX(-3px);}50%{transform:translateX(3px);}75%{transform:translateX(-2px);}100%{transform:translateX(0);}} .attackNudge{animation:attackNudge 160ms ease-in-out;} @keyframes attackNudge{0%{transform:translateX(0);}50%{transform:translateX(3px);}100%{transform:translateX(0);}} .states{font-size:.85rem;opacity:.9;margin-left:8px;} .statePill{display:inline-block;padding:1px 6px;border:1px solid rgba(255,255,255,.25);border-radius:999px;margin-left:6px;font-size:.78rem;} .sta-row{display:flex;align-items:center;gap:8px;margin-top:8px;} .sta-label{font-size:.85rem;opacity:.9;} .sta-bg{height:10px;width:160px;border-radius:6px;background:#222;overflow:hidden;} .sta-bar{height:100%;width:100%;transition:width 200ms ease-in-out;background:#5090e2;} .sta-txt{font-size:.85rem;opacity:.9;min-width:34px;text-align:right;} .fxBadge{display:inline-block;margin-top:6px;font-weight:900;letter-spacing:.3px;opacity:0;animation:fxBadge 650ms ease-out forwards;} @keyframes fxBadge{0%{opacity:0;transform:translateY(2px) scale(.98);}20%{opacity:1;}100%{opacity:0;transform:translateY(-10px) scale(1.02);}}</style>
<<script>>
(function(){
$(document).on(':passagedisplay',function(ev){
if(!ev||!ev.passage||ev.passage.title!=='MayorStory5')return;
const V=State.variables;
const F=V.Fight||(V.Fight={type:"?",lvl:1,playerMax:100,enemyMax:100,playerHP:100,enemyHP:100,playerBand:0,enemyBand:1,playerStaMax:5,playerSta:5,healCD:0,log:[],p:{},e:{}});
const $q=(sel)=>document.querySelector(sel);
function playPunchSfx(){try{if(!window.setup||!setup.AudioMixer)return;setup.AudioMixer.playPlaylist("sfx","sfx.punch",false,{fadeInMs:0,fadeOutMs:0});}catch(e){}}
function shouldPunch(mode){return mode==='atk'||mode==='heavy'||mode==='finish';}
const tip=$q('#fight-tip');
function tipShow(text){if(!tip)return;tip.textContent=text;tip.style.display='block';}
function tipHide(){if(!tip)return;tip.style.display='none';}
function tipMove(e){if(!tip||tip.style.display==='none')return;const pad=14;let x=e.clientX+pad,y=e.clientY+pad;const r=tip.getBoundingClientRect();if(x+r.width>window.innerWidth-8)x=e.clientX-r.width-pad;if(y+r.height>window.innerHeight-8)y=e.clientY-r.height-pad;tip.style.left=x+'px';tip.style.top=y+'px';}
function bindTips(root){if(!root)return;root.addEventListener('mousemove',tipMove,{passive:true});root.addEventListener('mouseover',function(e){const el=e.target&&e.target.closest?e.target.closest('[data-tip]'):null;if(!el)return;const t=el.getAttribute('data-tip');if(t&&t.trim())tipShow(t.trim());});root.addEventListener('mouseout',function(e){const el=e.target&&e.target.closest?e.target.closest('[data-tip]'):null;if(!el)return;const to=e.relatedTarget&&e.relatedTarget.closest?e.relatedTarget.closest('[data-tip]'):null;if(to===el)return;tipHide();});}
bindTips($q('.fight-ui'));
function pct(v,max){return Math.max(0,Math.min(100,Math.floor((v/max)*100)));}
function clamp(n,min,max){return(n<min?min:(n>max?max:n));}
function barColor(percent){if(percent>70)return"#2ecc71";if(percent>35)return"#f1c40f";return"#e74c3c";}
function setActionsEnabled(enabled){['#btn-atk','#btn-heavy','#btn-guard','#btn-heal','#btn-finish'].forEach(sel=>{const b=$q(sel);if(b)b.disabled=!enabled;});}
function setBtnVisible(sel,visible){const b=$q(sel);if(!b)return;b.style.display=visible?'':'none';}
function popNumber(target,text){const layer=$q(target);if(!layer)return;const el=document.createElement('div');el.className='dmg-pop';el.textContent=text;layer.appendChild(el);setTimeout(()=>{try{el.remove();}catch(e){}},700);}
function flashHit(cardSel,barBgSel){const c=$q(cardSel),b=$q(barBgSel);if(c){c.classList.remove('shake');c.classList.add('shake');setTimeout(()=>c.classList.remove('shake'),220);}if(b){b.classList.remove('hitFlash');b.classList.add('hitFlash');setTimeout(()=>b.classList.remove('hitFlash'),260);}}
function nudgeAttack(cardSel){const c=$q(cardSel);if(!c)return;c.classList.remove('attackNudge');c.classList.add('attackNudge');setTimeout(()=>c.classList.remove('attackNudge'),220);}
function showFx(text){const box=$q('#fight-stage');if(!box)return;const el=document.createElement('div');el.className='fxBadge';el.textContent=text;box.prepend(el);setTimeout(()=>{try{el.remove();}catch(e){}},700);}
function renderLog(){const box=$q('#fight-stage');if(!box)return;box.innerHTML='';}
function setBottom(wiki){const slot=$q('#fight-actionsbar');if(!slot)return;try{slot.innerHTML='';slot.appendChild(Wikifier.wikifyEval(String(wiki||'')));}catch(e){}}
function pushPopup(title,lines){const box=$q('#fight-popups');if(!box)return;try{box.innerHTML='';const t=String(title||'Info').replace(/"/g,'"');const arr=Array.isArray(lines)?lines:((lines!=null)?[String(lines)]:[]);const html=arr.filter(Boolean).map(s=>String(s)).join('<br>');box.appendChild(Wikifier.wikifyEval('<<InformationUiPopUp "'+t+'">>'+html+'<</InformationUiPopUp>>'));}catch(e){}}
function victoryScreen(){
const box=$q('#fight-stage');if(!box)return;
setActionsEnabled(false);box.innerHTML='';
pushPopup("Victory",["🏆 Victory! The enemy is defeated."]);
setBottom('<<BottomButton "Move">><<link "➡️ Continue">><<goto "MayorStory6">><</link>><</BottomButton>>');
}
function defeatScreen(){
const box=$q('#fight-stage');if(!box)return;
setActionsEnabled(false);box.innerHTML='';
pushPopup("Defeat",["💥 You are knocked out."]);
setBottom('<<BottomButton "Move">><<link "Continue">><<goto "End.Fight">><</link>><</BottomButton>>');
}
function applyDotsAndTick(sideKey,log){
const S=(sideKey==='p')?F.p:F.e;
if(S.bleed&&S.bleed>0){const dmg=Math.max(1,+S.bleedDmg||2);if(sideKey==='p'){F.playerHP=Math.max(0,F.playerHP-dmg);popNumber('#you-pop',`-${dmg}`);flashHit('#you-card','#you-barbg');log.push(`🩸 Bleeding tick on you: <strong>-${dmg} HP</strong>.`);}else{F.enemyHP=Math.max(0,F.enemyHP-dmg);popNumber('#foe-pop',`-${dmg}`);flashHit('#foe-card','#foe-barbg');log.push(`🩸 Bleeding tick on enemy: <strong>-${dmg} HP</strong>.`);}S.bleed-=1;}
if(S.guard&&S.guard>0)S.guard-=1;
if(S.exposed&&S.exposed>0)S.exposed-=1;
if(S.adr&&S.adr>0)S.adr-=1;
if(S.stun&&S.stun>0)S.stun-=1;
if(sideKey==='p'){V.Heal=F.playerHP;}
}
function pill(label,tipText){return`<span class="statePill" data-tip="${String(tipText).replace(/"/g,'"')}">${label}</span>`;}
function statePills(S){
let out=[];
if(S.stun>0)out.push(pill(`Stunned ${S.stun}`,"Stunned: skips the next turn."));
if(S.bleed>0)out.push(pill(`Bleeding ${S.bleed}`,"Bleeding: takes damage at the start of each turn."));
if(S.guard>0)out.push(pill("Guarded","Guarded: takes 50% less damage this turn."));
if(S.exposed>0)out.push(pill("Exposed","Exposed: takes 30% more damage."));
if(S.adr>0)out.push(pill("Adrenaline","Adrenaline: your next hit deals 50% more damage."));
return out.join('');
}
function updateHUD(){
const foeType=$q('#foe-type'),foeLvl=$q('#foe-lvl'),foeHP=$q('#foe-hp'),foeMax=$q('#foe-max'),foeBand=$q('#foe-band'),foeBar=$q('#foe-bar'),foeStates=$q('#foe-states');
const youFit=$q('#player-fit'),youHP=$q('#you-hp'),youMax=$q('#you-max'),youBand=$q('#you-band'),youBar=$q('#you-bar'),youStates=$q('#you-states');
const youSta=$q('#you-sta'),youStaTxt=$q('#you-sta-txt');
if(!foeType||!foeLvl||!foeHP||!foeMax||!foeBand||!foeBar||!youFit||!youHP||!youMax||!youBand||!youBar)return;
foeType.textContent=F.type;foeLvl.textContent=F.lvl;foeHP.textContent=F.enemyHP;foeMax.textContent=F.enemyMax;foeBand.textContent=F.enemyBand;
const foePct=pct(F.enemyHP,F.enemyMax);foeBar.style.width=foePct+'%';foeBar.style.background=barColor(foePct);
if(foeStates)foeStates.innerHTML=statePills(F.e);
const fit=Math.max(0,+V.Fitness||0);
youFit.textContent=fit;youHP.textContent=F.playerHP;youMax.textContent=F.playerMax;
const medQty=(V.Inventory&&V.Inventory.medkit&&Number.isFinite(+V.Inventory.medkit.qty))?Math.max(0,+V.Inventory.medkit.qty):0;
youBand.textContent=medQty;
const youPct=pct(F.playerHP,F.playerMax);youBar.style.width=youPct+'%';youBar.style.background=barColor(youPct);
if(youStates)youStates.innerHTML=statePills(F.p);
const staPct=pct(F.playerSta,F.playerStaMax);
if(youSta)youSta.style.width=staPct+'%';
if(youStaTxt)youStaTxt.textContent=`${F.playerSta}/${F.playerStaMax}`;
setBtnVisible('#btn-finish',(F.enemyHP>0&&(F.enemyHP/F.enemyMax)<=0.15));
const healBtn=$q('#btn-heal');
if(healBtn)healBtn.textContent=(F.healCD>0)?'🩹 Heal (CD)':'🩹 Heal';
}
function endCheck(){if(F.playerHP<=0){defeatScreen();return true;}if(F.enemyHP<=0){victoryScreen();return true;}return false;}
function atkBaseFrom(fit){return Math.floor(Math.random()*6)+6+Math.floor(fit/4);}
function enemyDodgeChance(){
let base=clamp(0.25+(Math.max(1,+F.lvl||1)/400),0.25,0.75);
base=clamp(base+((+F.enemyDodgeBias||0.5)-0.5)*0.25,0.15,0.85);
if(F.e.exposed>0)base=base*0.50;
return clamp(base,0.10,0.90);
}
function playerDodgeChance(fit){return clamp(0.10+(fit/200),0.10,0.60);}
function regenCooldownOnly(){if(F.healCD>0)F.healCD-=1;}
function startTurnTick(log){applyDotsAndTick('p',log);applyDotsAndTick('e',log);regenCooldownOnly();}
function enemyActs(log){
if(F.e.stun>0){log.push("😵 Enemy is stunned and skips the turn.");return;}
let action='atk';
const hpPct=F.enemyHP/F.enemyMax;
const roll=Math.random();
if(hpPct<=0.25&&F.enemyBand>0)action='heal';
else if(roll<0.20)action='guard';
else if(roll<0.40)action='heavy';
else action='atk';
if(action==='heal'){const h=Math.floor(F.enemyMax*(0.28+Math.random()*0.04));F.enemyHP=Math.min(F.enemyMax,F.enemyHP+h);F.enemyBand=Math.max(0,(+F.enemyBand||0)-1);showFx("Heal!");log.push(`🩹 Enemy heals: <strong>+${h} HP</strong>.`);return;}
if(action==='guard'){showFx("Guard!");F.e.guard=1;log.push("🛡️ Enemy takes a guarded stance.");return;}
const eFit=Math.max(0,+F.lvl||0);
let dmg=atkBaseFrom(eFit);
if(action==='heavy'){dmg=Math.floor(dmg*2.5);const dChance=enemyDodgeChance();if(Math.random()<dChance){log.push("🛡️ Enemy's heavy blow misses.");return;}showFx("Heavy!");log.push("💥 Enemy goes for a heavy blow!");}else{showFx("Attack!");}
if(F.p.guard>0)dmg=Math.floor(dmg*0.50);
if(F.p.exposed>0)dmg=Math.floor(dmg*1.30);
const fit=Math.max(0,+V.Fitness||0);
const pDodge=playerDodgeChance(fit);
if(action!=='heavy'&&Math.random()<pDodge){showFx("Evade!");log.push("🟦 You evade the enemy hit.");return;}
F.playerHP=Math.max(0,F.playerHP-dmg);
popNumber('#you-pop',`-${dmg}`);
flashHit('#you-card','#you-barbg');
log.push(`🔻 Enemy hits you: <strong>-${dmg} HP</strong>.`);
}
function spendSta(cost){if((+F.playerSta||0)<cost)return false;F.playerSta-=cost;return true;}
function doPlayerAttack(mode){
const fit=Math.max(0,+V.Fitness||0);
let log=[];
let cost=1;
if(mode==='heavy')cost=2;
if(mode==='heal')cost=2;
if(mode==='finish')cost=1;
if(mode==='guard')cost=0;
if(cost>0&&!spendSta(cost)){log.push("⚠️ Not enough stamina.");pushPopup("Fight",log);renderLog();updateHUD();return;}
if(mode==='guard')F.playerSta=clamp((+F.playerSta||0)+1,0,F.playerStaMax);
if(shouldPunch(mode))playPunchSfx();
startTurnTick(log);
if(endCheck()){updateHUD();return;}
if(mode==='guard'){showFx("Guard!");log.push("🛡️ You take a guarded stance. 50% less damage this turn.");F.p.guard=1;enemyActs(log);F.log=log;pushPopup("Fight",log);renderLog();updateHUD();endCheck();return;}
if(mode==='heal'){
if(F.healCD>0){log.push("⏳ Heal is on cooldown.");F.log=log;pushPopup("Fight",log);renderLog();updateHUD();return;}
const med=(V.Inventory&&V.Inventory.medkit)?V.Inventory.medkit:null;
const medQty=(med&&Number.isFinite(+med.qty))?Math.max(0,+med.qty):0;
if(medQty<=0){log.push("❌ You don't have a Medkit.");F.log=log;pushPopup("Fight",log);renderLog();updateHUD();return;}
V.Inventory.medkit.qty=Math.max(0,medQty-1);
const heal=Math.floor(F.playerMax*(0.28+Math.random()*0.04));
F.playerHP=Math.min(F.playerMax,F.playerHP+heal);
F.healCD=1;showFx("Heal!");log.push(`🩹 You heal: <strong>+${heal} HP</strong>.`);
enemyActs(log);F.log=log;pushPopup("Fight",log);renderLog();updateHUD();endCheck();return;
}
if(mode==='finish'){
if((F.enemyHP/F.enemyMax)>0.15){log.push("☠️ Finisher not available yet.");F.log=log;pushPopup("Fight",log);renderLog();updateHUD();return;}
showFx("Finisher!");log.push("☠️ You execute a brutal finisher!");F.enemyHP=0;popNumber('#foe-pop','KO');flashHit('#foe-card','#foe-barbg');F.log=log;pushPopup("Fight",log);renderLog();updateHUD();endCheck();return;
}
nudgeAttack('#you-card');
let dmg=atkBaseFrom(fit);
if(mode==='heavy'){
dmg=Math.floor(dmg*2.5);
showFx("Heavy!");log.push("💥 Heavy attack.");
const dChance=enemyDodgeChance();
if(Math.random()<dChance){showFx("Evaded!");log.push("🛡️ Enemy dodges the heavy blow.");F.log=log;pushPopup("Fight",log);renderLog();enemyActs(log);updateHUD();endCheck();return;}
if(F.p.adr>0){dmg=Math.floor(dmg*1.50);F.p.adr=0;log.push("⚡ Adrenaline boosts your strike.");}
if(F.e.exposed>0)dmg=Math.floor(dmg*1.30);
if(F.e.guard>0)dmg=Math.floor(dmg*0.50);
F.enemyHP=Math.max(0,F.enemyHP-dmg);
popNumber('#foe-pop',`-${dmg}`);flashHit('#foe-card','#foe-barbg');
F.p.adr=1;log.push(`🔺 Heavy hit lands: <strong>-${dmg} HP</strong>. Adrenaline builds.`);
} else {
showFx("Attack!");log.push("🥊 Standard attack.");
if(F.p.adr>0){dmg=Math.floor(dmg*1.50);F.p.adr=0;log.push("⚡ Adrenaline boosts your strike.");}
if(F.e.exposed>0)dmg=Math.floor(dmg*1.30);
if(F.e.guard>0)dmg=Math.floor(dmg*0.50);
const dChance=enemyDodgeChance();
if(Math.random()<dChance){const reduced=Math.floor(dmg*0.40);F.enemyHP=Math.max(0,F.enemyHP-reduced);popNumber('#foe-pop',`-${reduced}`);if(reduced>0)flashHit('#foe-card','#foe-barbg');log.push(`🛡️ Enemy partially dodges. Damage reduced to <strong>-${reduced} HP</strong>.`);}
else{F.enemyHP=Math.max(0,F.enemyHP-dmg);popNumber('#foe-pop',`-${dmg}`);flashHit('#foe-card','#foe-barbg');log.push(`🔺 You hit: <strong>-${dmg} HP</strong>.`);}
}
enemyActs(log);F.log=log;pushPopup("Fight",log);renderLog();updateHUD();endCheck();
}
function bind(sel,fn){const b=$q(sel);if(!b)return;const clone=b.cloneNode(true);b.parentNode.replaceChild(clone,b);clone.addEventListener('click',fn);}
bind('#btn-atk',()=>doPlayerAttack('atk'));
bind('#btn-heavy',()=>doPlayerAttack('heavy'));
bind('#btn-guard',()=>doPlayerAttack('guard'));
bind('#btn-heal',()=>doPlayerAttack('heal'));
bind('#btn-finish',()=>doPlayerAttack('finish'));
setBottom('');
pushPopup("Fight",["Choose an action."]);
updateHUD();
renderLog();
});
})();
<</script>><<sound "music" "music.main" true>><<passagebg>><img src="assets/img/misc/dead.gif"/><</passagebg>><<InformationUiPopUp "Fought to the death">>
You are dead! You <strong>fought to the death</strong>, and you lost the fight...
<</InformationUiPopUp>>
<div class="BottomUiBarCustom">
<<BottomButton "Story">><<Restart>><</BottomButton>>
</div><<sound "music" "music.music" true>><<passagebg>><<sound "bg" "bg.empty" true>><img src="assets/img/story/mayorstory/archives.webp"/><</passagebg>>
<<InformationUiPopUp>>Silence falls again. The other man is on the floor, dazed. I catch my breath, hands on my knees, and scan the room. The file has fallen against the base of a cabinet. I pick it up, quickly check that the pages are intact, and slip it under my jacket. Then I hear voices in the corridor, the guards heard the noise.
<</InformationUiPopUp>>
<<InformationUiPopUp>>I cut my flashlight and head toward the emergency exit at the back of the room, the one I had spotted on the way in. The voices are getting closer, heavy footsteps.
<</InformationUiPopUp>>
<<revealtext "exit">><<passagebg>><<sound "bg" "bg.cityNight" true>><img src="assets/img/misc/city/citynight.webp"/><</passagebg>><<InformationUiPopUp>>I push the panic bar without a sound, just enough to slip through, and move into the service corridor. Once outside, I pull off my balaclava, the cold night air hits my face. I hug the wall in the shadows, circle around the back of the building, and move away quickly without running. Two streets further, I glance back, nothing, no one following me. I slip my hand under my jacket and feel the file still there, intact. The GE-2017-114 archive is mine now.
<</InformationUiPopUp>><</revealtext>>
<div class="BottomUiBarCustom">
<<BottomButton "Decision">><<revealbtn "exit" "🚪 Exit" "moveBtn">><</revealbtn>><</BottomButton>>
<<BottomButton "Move" "moveBtn">><<link "➡️ Finally done for tonight...">><<goto "City">><<set $MayorStoryInfo3 = true>><<set $Inventory.archivefile = {id:"archivefile", name:"Archive File", price:0, img:"assets/img/items/story/archivefile.webp", unique:true, inventory:true, bought:true, desc:"A useful item for the story.", qty:1}>><</link>><</BottomButton>>
</div><<sound "music" "music.music" true>><<sound "bg" "bg.empty" true>><<passagebg>><<if $Time !== 3>><img src="assets/img/misc/home/mcbedroom.webp"><<else>><img src="assets/img/misc/home/mcbedroomnight.webp"><</if>><</passagebg>>
<<InformationUiPopUp>>Back in my room. I set the GE-2017-114 file on the desk, take off my jacket, and sit down.
<</InformationUiPopUp>>
<<InformationUiPopUp>>I start reading. Skimming at first, just trying to understand what I'm looking at. A geological survey from 2017. Soil composition data, ground displacement maps, technical annotations I have to read twice to make sense of. Then something catches my eye. A parcel reference number. A specific location in the financial district.
<</InformationUiPopUp>>
<<TalkMC "The plan was simple from the start, have something people want to get back and use it as leverage. But it's way too strange, just for a geological survey, that someone wanted this file badly enough to send a man in the middle of the night to steal it. There's clearly something off behind all of this.">>
<<InformationUiPopUp>>I open my laptop.
<</InformationUiPopUp>>
<<revealtext "search">><<passagebg>><img src="assets/img/misc/MCPC/internet/email/reading.gif"/><</passagebg>><<InformationUiPopUp>>I start with the parcel reference number. The result comes up immediately. A site in the financial district, currently under a construction contract held by the Hargrove Development Group. Delivery expected in several months. A large mixed-use building, commercial ground floor, residential above. The kind of project that costs a lot and makes even more.
<</InformationUiPopUp>>
<<TalkMC "So a group with a major construction contract sends someone to steal a geological survey of the exact site they're building on. I don't understand everything yet...">>
<<InformationUiPopUp>>I keep searching.
<</InformationUiPopUp>>
<<InformationUiPopUp>>Hargrove Development Group. I search the name. Corporate filings, press releases, local news articles. At first glance it looks like any mid-sized real estate firm. Projects across several states. A board of directors with clean headshots and forgettable bios. Then I dig deeper. Financial reports, trade publications. An article from a few months ago about refinancing difficulties. Another mentioning delayed payments to contractors on a project in another city. A third about a credit rating downgrade.
<</InformationUiPopUp>>
<<TalkMC "Hargrove is in trouble... A group in that kind of financial shape doesn't finance a project of this scale through conventional channels, and I can't see any bank funding something at this level with that much risk of it falling apart. The numbers don't add up.">>
<<InformationUiPopUp>>I look at the file again. The geological data. The ground displacement. The soil composition issues that would make any serious construction on that parcel significantly more complex and significantly more expensive. If this information had been factored into the project from the start, the budget would look completely different. And especially the timeline, we'd be talking years, not months.
<</InformationUiPopUp>>
<<TalkMC "But the project only started not that long ago, and given the projected construction timeline, either the Hargrove group doesn't know, or they know and they're hiding it. Given that someone just tried to steal the only document that proves it, I'm not betting on the first option.">>
<<InformationUiPopUp>>I close the laptop.
<</InformationUiPopUp>><</revealtext>>
<<revealtext "close">><<passagebg>><<if $Time !== 3>><img src="assets/img/misc/home/mcbedroom.webp"><<else>><img src="assets/img/misc/home/mcbedroomnight.webp"><</if>><</passagebg>><<TalkMC "A group that's financially stretched, backed by money I can't fully trace, building on a site with geological problems they've kept off the books. That's not just a bad investment. That's something someone is holding together with pressure and silence, and it only stays standing as long as nobody looks too closely.">>
<<InformationUiPopUp>>I look at the ceiling for a long moment.
<</InformationUiPopUp>>
<<TalkMC "I don't know everything yet. I don't know who's financing them, I don't know how far the cover goes, and I don't know what could happen if it all came crashing down. But I know this file matters a great deal to them. Use it the right way, at the right moment, with the right person, and I could stand to gain a lot.">>
<<TalkMC "And if they were to lose their construction rights, that parcel would go back to the city...">>
<<InformationUiPopUp>>The mayor. If I can get close enough, if she trusts me enough, she becomes the key piece. She can block the permits, flag the discrepancies, push the right pressure points inside the administration. And when Hargrove is out, when the site is back on the table, I'll already be standing next to the person who will decide what happens to it.
<</InformationUiPopUp>>
<<TalkMC "It's not a completely clean plan yet, there are too many things I still don't know. But I already have a direction, and for now that direction is enough.">>
<<InformationUiPopUp>>I close the file and hide it in my room.
<</InformationUiPopUp>>
<<TalkMC "I need to get to the town hall...">>
<</revealtext>>
<div class="BottomUiBarCustom">
<<BottomButton "Story">><<revealbtn "search" "🔍 Search" "" "" "close" true>><</revealbtn>><<revealbtn "close" "➡️ Close" "moveBtn" "close" "" false>><</revealbtn>><</BottomButton>><<BottomButton "Story" "moveBtn">><<link "➡️ Interesting...">><<goto "MCBedroom">><<set $MayorStoryInfo4 = true>><</link>><</BottomButton>>
</div><<sound "music" "music.music" true>><<passagebg>><<sound "bg" "bg.city" true>><img src="assets/img/misc/city/cityhall/cityhall.webp"/><</passagebg>>
<<InformationUiPopUp>>Leaving the mayor's office, I make my way down the corridor toward the exit. Two voices reach me from a recess near the stairwell. I slow down without stopping, just enough to hear.
<</InformationUiPopUp>>
<<TalkRandom "Strange Man" "assets/img/character/npc/b1.jpg" "The guy we sent got caught last night.">>
<<TalkRandom "Strange Man" "assets/img/character/npc/b4.jpg" "I know. And from what he told the others before we got to him, he wasn't alone in the archives.">>
<<TalkRandom "Strange Man" "assets/img/character/npc/b4.jpg" "Someone got there before us...">>
<<TalkRandom "Strange Man" "assets/img/character/npc/b2.jpg" "This is really bad... We don't know who it is, we don't know who they're working for, we have absolutely no fucking information.">>
<<TalkRandom "Strange Man" "assets/img/character/npc/b1.jpg" "If that file falls into the wrong hands...">>
<<TalkRandom "Strange Man" "assets/img/character/npc/b4.jpg" "It's already in the wrong hands. That's what I'm trying to make you understand. If Hargrove goes down because of this, we go down with them. We have no choice, we need to find whoever has it.">>
<<TalkRandom "Strange Man" "assets/img/character/npc/b1.jpg" "Did you see what happened with the zoning vote? The mayor pulled out an annex nobody was expecting. She couldn't have gotten that on her own.">>
<<TalkRandom "Strange Man" "assets/img/character/npc/b4.jpg" "I thought about that. But if the mayor had the file in her hands, it would already be over, she wouldn't have waited.">>
<<TalkRandom "Strange Man" "assets/img/character/npc/b1.jpg" "So someone else is feeding her information?">>
<<TalkRandom "Strange Man" "assets/img/character/npc/b4.jpg" "Exactly. The same person or group that took the file before us. They're using what's in it to help the mayor, to block us without her being directly involved.">>
<<TalkRandom "Strange Man" "assets/img/character/npc/b1.jpg" "Why? Why not just go to the police or hand it over directly?">>
<<TalkRandom "Strange Man" "assets/img/character/npc/b4.jpg" "How the hell would I know? Maybe because they want something. People who do this always want something. We don't know what yet, but that doesn't matter. What matters is finding them before they go any further.">>
<<TalkRandom "Strange Man" "assets/img/character/npc/b1.jpg" "Where do we start?">>
<<TalkRandom "Strange Man" "assets/img/character/npc/b4.jpg" "The archives. Someone went in that night at the same time as our guy, there has to be a trace somewhere. A camera, a guard, something...">>
<<InformationUiPopUp>>Their voices fade as I continue toward the exit, steady pace, neutral expression. They didn't notice me. They don't know yet who they're looking for. And now that I do, I'm going to have to be careful about what comes next.
<</InformationUiPopUp>>
<div class="BottomUiBarCustom">
<<BottomButton "Move">><<link "➡️ Ok, go next...">><<goto "CityHall">><<set $MayorStoryInfo5 = true>><</link>><</BottomButton>>
</div><<sound "music" "music.music" true>><<sound "bg" "bg.city" true>><<passagebg>><img src="assets/img/misc/city/city.webp"/><</passagebg>>
<<InformationUiPopUp>>I find myself in town, nothing out of the ordinary so far, just going about my usual business. But something feels off, I have a bad feeling. There's someone I've seen multiple times in a short window, and the few times I try to glance in their direction without looking directly at them, they're watching me before looking away. I don't let anything show, I just keep walking normally.
<</InformationUiPopUp>>
<<TalkMC "Okay... first rule: don't let on that you noticed.">>
<<InformationUiPopUp>>I take a meaningless street, heading toward the Mall. The figure follows.
<</InformationUiPopUp>>
<<revealtext "mall">><<passagebg>><<sound "bg" "bg.mall" true>><img src="assets/img/misc/city/mall/mall.webp"/><</passagebg>><<InformationUiPopUp>>Once inside the mall, I walk into a random store, pretend to browse for a couple of minutes, and walk back out the same door. I take my time, moving casually so it doesn't look like I'm testing anything.
<</InformationUiPopUp>>
<<InformationUiPopUp>>Then once I'm back in the city center, I change direction, heading toward the old district.
<</InformationUiPopUp>><</revealtext>>
<<revealtext "oldtown">><<passagebg>><<sound "bg" "bg.city" true>><img src="assets/img/misc/oldtown/oldtown.webp"/><</passagebg>><<InformationUiPopUp>>In the old district, the streets are pretty quiet, less people around, which makes it harder to blend in. I deliberately walk into the TrapHouse. Inside, I don't go upstairs, I just quietly look through the windows. I can see him at the end of the alley, keeping an eye on the building, clearly waiting for me to come back out.
<</InformationUiPopUp>>
<<TalkMC "Confirmed. Someone's following me.">>
<<InformationUiPopUp>>I decide to wait a little, then I step out of the building, heading for the park.
<</InformationUiPopUp>><</revealtext>>
<<revealtext "park">><<passagebg>><<sound "bg" "bg.park" true>><img src="assets/img/misc/city/park/park.webp"/><</passagebg>><<InformationUiPopUp>>Once in the park, I keep walking, then decide to sit down on a bench, not far from a playground full of people. That way, if he decided to try something, it would be a lot harder with this many people around.
<</InformationUiPopUp>>
<<TalkMC "I need to lose him. I can't just sit here waiting, and I'm definitely not going home while I'm being followed.">>
<<InformationUiPopUp>>I stay seated for a while, enough to let his guard drop, then I glance in his direction so he looks away.
<</InformationUiPopUp>>
<<TalkMC "Okay, this is the moment. Time to go.">><</revealtext>>
<<revealtext "escape">><<InformationUiPopUp>>I get up without hesitating and pick up the pace immediately. The park is big, dense, and has several exits. It's my best shot.
<</InformationUiPopUp>>
<<InformationUiPopUp>>I turn quickly to check if he noticed I've moved, and sure enough, I can see him far behind me, running now, all discretion gone. He figured out that I figured out. We're nowhere near a subtle tail anymore.
<</InformationUiPopUp>>
<<InformationUiPopUp>>At the first intersection I hit, I immediately cut onto a side path instead of going straight. I hug a row of trees, cut behind a group of people having a picnic, cut again, checking over my shoulder every so often to make sure he's really not behind me anymore.
<</InformationUiPopUp>>
<<InformationUiPopUp>>After several minutes of zigzagging through the park, I stop behind a thick cluster of trees. I watch the visible paths. Nobody. I catch my breath slowly, quietly.
<</InformationUiPopUp>>
<<TalkMC "Okay. Looks like I'm clear for now.">>
<<InformationUiPopUp>>I wait another two minutes without moving, eyes on the park entrances. Nothing. I finally leave through an exit on the opposite side from where I came in, then take back streets through parts of the city I don't usually use, and head home.
<</InformationUiPopUp>>
<<TalkMC "So Hargrove figured out who I was. That changes things now.">>
<</revealtext>>
<div class="BottomUiBarCustom">
<<BottomButton "Story">><<revealbtn "mall" "➡️ Go to the Mall" "" "" "oldtown" true>><</revealbtn>><<revealbtn "oldtown" "➡️ Go to the Oldtown" "" "oldtown" "park" false>><</revealbtn>><<revealbtn "park" "➡️ Go to the Park" "" "park" "escape" false>><</revealbtn>><<revealbtn "escape" "🏃 Run" "moveBtn" "escape" "" false>><</revealbtn>><</BottomButton>><<BottomButton "Story" "moveBtn">><<link "➡️ Damn it...">><<goto "HomeEntrance">><<set $MayorStoryInfo6 = true>><<set $Time++>><</link>><</BottomButton>>
</div><<sound "music" "music.music" true>><<sound "bg" "bg.city" true>><<passagebg>><img src="assets/img/misc/city/city.webp"/><</passagebg>>
<<InformationUiPopUp>>I'm hanging around downtown, not far from the mall. The day is going normally until a woman approaches me quickly, looking clearly panicked.
<</InformationUiPopUp>>
<<TalkRandom "Woman" "assets/img/character/npc/g8.jpg" "Excuse me, please, can you help me?">>
<<TalkMC "What's going on?">>
<<TalkRandom "Woman" "assets/img/character/npc/g8.jpg" "There's a man who's been following me for a while, I tried changing direction several times but he keeps coming, I'm scared, I don't know what to do.">>
<<InformationUiPopUp>>I glance behind the woman, and sure enough, there's a man, somewhere in his thirties, built, walking toward us with purpose, his eyes fixed on the woman in front of me. He slows slightly when he sees me, but doesn't stop.
<</InformationUiPopUp>>
<<TalkRandom "Man" "assets/img/character/npc/b3.jpg" "Hey, you. I know her, I just want to talk to her, so step aside.">>
<<TalkMC "She really doesn't look like she knows you.">>
<<TalkRandom "Man" "assets/img/character/npc/b3.jpg" "Look, I've been nice about it, but if you don't walk away right now this is just going to end badly.">>
<<InformationUiPopUp>>He keeps moving forward, deliberately ignoring my presence like I'm just a temporary obstacle. The woman takes a step back behind me.
<</InformationUiPopUp>>
<<TalkMC "I don't think you got the message. She doesn't want to talk to you.">>
<<TalkRandom "Man" "assets/img/character/npc/b3.jpg" "Tch. Shut your mouth, don't bust my balls, I'm not gonna waste my time talking to you.">>
<<InformationUiPopUp>>He doesn't wait for an answer. He comes straight at me, fists already clenched.
<</InformationUiPopUp>>
<<InformationUiPopUp "⚠️ Important ⚠️" "#e65763">>It is advised to save here, you can lose the game during this fight!
<</InformationUiPopUp>>
<div class="BottomUiBarCustom">
<<BottomButton "Action">><<link "💥 Fight">><<goto "MayorStory11">><</link>><</BottomButton>>
</div><<set $Fight = {
type: "Man",
lvl: 60,
playerMax: $HealMax,
playerHP: $Heal,
enemyMax: 135,
enemyHP: 135,
playerBand: 0,
enemyBand: 1,
playerStaMax: 5,
playerSta: 5,
healCD: 0,
log: [],
p: {},
e: {},
enemyDodgeBias: 0.55
}>><<sound "music" "music.fight" true>><<sound "bg" "bg.city" true>><<passagebg>><img src="assets/img/misc/city/city.webp"/><</passagebg>><div id="fight-tip" style="display:none;"></div><div class="fight-ui" style="max-width:960px;margin:auto;"><div id="foe-card" class="foes card" style="display:flex;gap:12px;justify-content:space-between;align-items:center;padding:10px;border:1px solid #444;border-radius:10px;margin-bottom:10px;"><div style="width:100%;"><p style="margin:0;"><strong>Enemy:</strong> <span id="foe-type"></span> (Fitness <span id="foe-lvl"></span>) <span id="foe-states" class="states"></span></p><div class="hp-bar-bg" id="foe-barbg"><div id="foe-bar" class="hp-bar"></div><div class="pop-layer" id="foe-pop"></div></div><p style="margin:4px 0 0 0;">HP <span id="foe-hp"></span> / <span id="foe-max"></span> · 🩹 <span id="foe-band"></span></p></div></div><div id="you-card" class="you card" style="display:flex;gap:12px;justify-content:space-between;align-items:center;padding:10px;border:1px solid #444;border-radius:10px;margin-bottom:14px;"><div style="width:100%;"><p style="margin:0;"><strong>You</strong> (Fitness <span id="player-fit"></span>) <span id="you-states" class="states"></span></p><div class="hp-bar-bg" id="you-barbg"><div id="you-bar" class="hp-bar"></div><div class="pop-layer" id="you-pop"></div></div><div class="sta-row"><span class="sta-label">Stamina</span><div class="sta-bg"><div id="you-sta" class="sta-bar"></div></div><span id="you-sta-txt" class="sta-txt"></span></div><p style="margin:4px 0 0 0;">HP <span id="you-hp"></span> / <span id="you-max"></span> · 🩹 <span id="you-band"></span></p></div></div><div id="fight-actions" style="display:flex;gap:10px;flex-wrap:wrap;margin-bottom:10px;"><button id="btn-atk" type="button" data-tip="Standard attack. Deals solid damage based on your Fitness. Cost: 1 stamina.">🥊 Attack</button><button id="btn-heavy" type="button" data-tip="Heavy attack. Deals 2.5x damage based on Fitness, but costs 2 stamina and misses more often.">💥 Heavy</button><button id="btn-guard" type="button" data-tip="Guard. You take 50% less damage this turn. Cost: 0 stamina. Gain: +1 stamina.">🛡️ Guard</button><button id="btn-heal" type="button" data-tip="Heal using a Medkit. Cooldown: every other turn. Cost: 2 stamina. Requires: 1 Medkit.">🩹 Heal</button><button id="btn-finish" type="button" style="display:none;" data-tip="Finisher. Available when enemy HP is 15% or less. Ends the fight instantly. Cost: 1 stamina.">☠️ Finisher</button></div><div id="fight-popups"></div><div id="fight-stage"></div></div><div class="BottomUiBarCustom"><span style="display:contents;" id="fight-actionsbar"></span></div><style>#fight-tip{position:fixed;z-index:99999;display:none;max-width:280px;padding:8px 10px;border:1px solid rgba(255,255,255,.25);border-radius:10px;background:rgba(10,10,10,.92);backdrop-filter:blur(3px);color:#fff;font-size:.9rem;line-height:1.25;pointer-events:none;box-shadow:0 6px 18px rgba(0,0,0,.35);} .fight-ui p{line-height:1.3;} .fight-ui .card{background:rgba(255,255,255,0.03);} #fight-actions button{padding:8px 12px;border:1px solid #666;border-radius:8px;background:transparent;cursor:pointer;color:#fff;} #fight-actions button:hover{background:rgba(255,255,255,0.06);} #fight-actions button:disabled{opacity:.45;cursor:not-allowed;} .hp-bar-bg{position:relative;height:14px;background:#222;border-radius:7px;overflow:hidden;margin-top:6px;} .hp-bar{height:100%;width:100%;transition:width 250ms ease-in-out,background 250ms linear;} .pop-layer{position:absolute;inset:0;pointer-events:none;overflow:visible;} .dmg-pop{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);font-weight:800;opacity:0;animation:popFloat 650ms ease-out forwards;text-shadow:0 1px 0 rgba(0,0,0,.55);} @keyframes popFloat{0%{opacity:0;transform:translate(-50%,-40%) scale(.9);}15%{opacity:1;}100%{opacity:0;transform:translate(-50%,-140%) scale(1.05);}} .hitFlash{animation:hitFlash 220ms ease-out;} @keyframes hitFlash{0%{filter:none;}40%{filter:brightness(1.35);}100%{filter:none;}} .shake{animation:shake 180ms ease-in-out;} @keyframes shake{0%{transform:translateX(0);}25%{transform:translateX(-3px);}50%{transform:translateX(3px);}75%{transform:translateX(-2px);}100%{transform:translateX(0);}} .attackNudge{animation:attackNudge 160ms ease-in-out;} @keyframes attackNudge{0%{transform:translateX(0);}50%{transform:translateX(3px);}100%{transform:translateX(0);}} .states{font-size:.85rem;opacity:.9;margin-left:8px;} .statePill{display:inline-block;padding:1px 6px;border:1px solid rgba(255,255,255,.25);border-radius:999px;margin-left:6px;font-size:.78rem;} .sta-row{display:flex;align-items:center;gap:8px;margin-top:8px;} .sta-label{font-size:.85rem;opacity:.9;} .sta-bg{height:10px;width:160px;border-radius:6px;background:#222;overflow:hidden;} .sta-bar{height:100%;width:100%;transition:width 200ms ease-in-out;background:#5090e2;} .sta-txt{font-size:.85rem;opacity:.9;min-width:34px;text-align:right;} .fxBadge{display:inline-block;margin-top:6px;font-weight:900;letter-spacing:.3px;opacity:0;animation:fxBadge 650ms ease-out forwards;} @keyframes fxBadge{0%{opacity:0;transform:translateY(2px) scale(.98);}20%{opacity:1;}100%{opacity:0;transform:translateY(-10px) scale(1.02);}}</style>
<<script>>
(function(){
$(document).on(':passagedisplay',function(ev){
if(!ev||!ev.passage||ev.passage.title!=='MayorStory11')return;
const V=State.variables;
const F=V.Fight||(V.Fight={type:"?",lvl:1,playerMax:100,enemyMax:100,playerHP:100,enemyHP:100,playerBand:0,enemyBand:1,playerStaMax:5,playerSta:5,healCD:0,log:[],p:{},e:{}});
const $q=(sel)=>document.querySelector(sel);
function playPunchSfx(){try{if(!window.setup||!setup.AudioMixer)return;setup.AudioMixer.playPlaylist("sfx","sfx.punch",false,{fadeInMs:0,fadeOutMs:0});}catch(e){}}
function shouldPunch(mode){return mode==='atk'||mode==='heavy'||mode==='finish';}
const tip=$q('#fight-tip');
function tipShow(text){if(!tip)return;tip.textContent=text;tip.style.display='block';}
function tipHide(){if(!tip)return;tip.style.display='none';}
function tipMove(e){if(!tip||tip.style.display==='none')return;const pad=14;let x=e.clientX+pad,y=e.clientY+pad;const r=tip.getBoundingClientRect();if(x+r.width>window.innerWidth-8)x=e.clientX-r.width-pad;if(y+r.height>window.innerHeight-8)y=e.clientY-r.height-pad;tip.style.left=x+'px';tip.style.top=y+'px';}
function bindTips(root){if(!root)return;root.addEventListener('mousemove',tipMove,{passive:true});root.addEventListener('mouseover',function(e){const el=e.target&&e.target.closest?e.target.closest('[data-tip]'):null;if(!el)return;const t=el.getAttribute('data-tip');if(t&&t.trim())tipShow(t.trim());});root.addEventListener('mouseout',function(e){const el=e.target&&e.target.closest?e.target.closest('[data-tip]'):null;if(!el)return;const to=e.relatedTarget&&e.relatedTarget.closest?e.relatedTarget.closest('[data-tip]'):null;if(to===el)return;tipHide();});}
bindTips($q('.fight-ui'));
function pct(v,max){return Math.max(0,Math.min(100,Math.floor((v/max)*100)));}
function clamp(n,min,max){return(n<min?min:(n>max?max:n));}
function barColor(percent){if(percent>70)return"#2ecc71";if(percent>35)return"#f1c40f";return"#e74c3c";}
function setActionsEnabled(enabled){['#btn-atk','#btn-heavy','#btn-guard','#btn-heal','#btn-finish'].forEach(sel=>{const b=$q(sel);if(b)b.disabled=!enabled;});}
function setBtnVisible(sel,visible){const b=$q(sel);if(!b)return;b.style.display=visible?'':'none';}
function popNumber(target,text){const layer=$q(target);if(!layer)return;const el=document.createElement('div');el.className='dmg-pop';el.textContent=text;layer.appendChild(el);setTimeout(()=>{try{el.remove();}catch(e){}},700);}
function flashHit(cardSel,barBgSel){const c=$q(cardSel),b=$q(barBgSel);if(c){c.classList.remove('shake');c.classList.add('shake');setTimeout(()=>c.classList.remove('shake'),220);}if(b){b.classList.remove('hitFlash');b.classList.add('hitFlash');setTimeout(()=>b.classList.remove('hitFlash'),260);}}
function nudgeAttack(cardSel){const c=$q(cardSel);if(!c)return;c.classList.remove('attackNudge');c.classList.add('attackNudge');setTimeout(()=>c.classList.remove('attackNudge'),220);}
function showFx(text){const box=$q('#fight-stage');if(!box)return;const el=document.createElement('div');el.className='fxBadge';el.textContent=text;box.prepend(el);setTimeout(()=>{try{el.remove();}catch(e){}},700);}
function renderLog(){const box=$q('#fight-stage');if(!box)return;box.innerHTML='';}
function setBottom(wiki){const slot=$q('#fight-actionsbar');if(!slot)return;try{slot.innerHTML='';slot.appendChild(Wikifier.wikifyEval(String(wiki||'')));}catch(e){}}
function pushPopup(title,lines){const box=$q('#fight-popups');if(!box)return;try{box.innerHTML='';const t=String(title||'Info').replace(/"/g,'"');const arr=Array.isArray(lines)?lines:((lines!=null)?[String(lines)]:[]);const html=arr.filter(Boolean).map(s=>String(s)).join('<br>');box.appendChild(Wikifier.wikifyEval('<<InformationUiPopUp "'+t+'">>'+html+'<</InformationUiPopUp>>'));}catch(e){}}
function victoryScreen(){
const box=$q('#fight-stage');if(!box)return;
setActionsEnabled(false);box.innerHTML='';
pushPopup("Victory",["🏆 Victory! The enemy is defeated."]);
setBottom('<<BottomButton "Move">><<link "➡️ Continue">><<goto "MayorStory12">><</link>><</BottomButton>>');
}
function defeatScreen(){
const box=$q('#fight-stage');if(!box)return;
setActionsEnabled(false);box.innerHTML='';
pushPopup("Defeat",["💥 You are knocked out."]);
setBottom('<<BottomButton "Move">><<link "Continue">><<goto "End.Fight">><</link>><</BottomButton>>');
}
function applyDotsAndTick(sideKey,log){
const S=(sideKey==='p')?F.p:F.e;
if(S.bleed&&S.bleed>0){const dmg=Math.max(1,+S.bleedDmg||2);if(sideKey==='p'){F.playerHP=Math.max(0,F.playerHP-dmg);popNumber('#you-pop',`-${dmg}`);flashHit('#you-card','#you-barbg');log.push(`🩸 Bleeding tick on you: <strong>-${dmg} HP</strong>.`);}else{F.enemyHP=Math.max(0,F.enemyHP-dmg);popNumber('#foe-pop',`-${dmg}`);flashHit('#foe-card','#foe-barbg');log.push(`🩸 Bleeding tick on enemy: <strong>-${dmg} HP</strong>.`);}S.bleed-=1;}
if(S.guard&&S.guard>0)S.guard-=1;
if(S.exposed&&S.exposed>0)S.exposed-=1;
if(S.adr&&S.adr>0)S.adr-=1;
if(S.stun&&S.stun>0)S.stun-=1;
if(sideKey==='p'){V.Heal=F.playerHP;}
}
function pill(label,tipText){return`<span class="statePill" data-tip="${String(tipText).replace(/"/g,'"')}">${label}</span>`;}
function statePills(S){
let out=[];
if(S.stun>0)out.push(pill(`Stunned ${S.stun}`,"Stunned: skips the next turn."));
if(S.bleed>0)out.push(pill(`Bleeding ${S.bleed}`,"Bleeding: takes damage at the start of each turn."));
if(S.guard>0)out.push(pill("Guarded","Guarded: takes 50% less damage this turn."));
if(S.exposed>0)out.push(pill("Exposed","Exposed: takes 30% more damage."));
if(S.adr>0)out.push(pill("Adrenaline","Adrenaline: your next hit deals 50% more damage."));
return out.join('');
}
function updateHUD(){
const foeType=$q('#foe-type'),foeLvl=$q('#foe-lvl'),foeHP=$q('#foe-hp'),foeMax=$q('#foe-max'),foeBand=$q('#foe-band'),foeBar=$q('#foe-bar'),foeStates=$q('#foe-states');
const youFit=$q('#player-fit'),youHP=$q('#you-hp'),youMax=$q('#you-max'),youBand=$q('#you-band'),youBar=$q('#you-bar'),youStates=$q('#you-states');
const youSta=$q('#you-sta'),youStaTxt=$q('#you-sta-txt');
if(!foeType||!foeLvl||!foeHP||!foeMax||!foeBand||!foeBar||!youFit||!youHP||!youMax||!youBand||!youBar)return;
foeType.textContent=F.type;foeLvl.textContent=F.lvl;foeHP.textContent=F.enemyHP;foeMax.textContent=F.enemyMax;foeBand.textContent=F.enemyBand;
const foePct=pct(F.enemyHP,F.enemyMax);foeBar.style.width=foePct+'%';foeBar.style.background=barColor(foePct);
if(foeStates)foeStates.innerHTML=statePills(F.e);
const fit=Math.max(0,+V.Fitness||0);
youFit.textContent=fit;youHP.textContent=F.playerHP;youMax.textContent=F.playerMax;
const medQty=(V.Inventory&&V.Inventory.medkit&&Number.isFinite(+V.Inventory.medkit.qty))?Math.max(0,+V.Inventory.medkit.qty):0;
youBand.textContent=medQty;
const youPct=pct(F.playerHP,F.playerMax);youBar.style.width=youPct+'%';youBar.style.background=barColor(youPct);
if(youStates)youStates.innerHTML=statePills(F.p);
const staPct=pct(F.playerSta,F.playerStaMax);
if(youSta)youSta.style.width=staPct+'%';
if(youStaTxt)youStaTxt.textContent=`${F.playerSta}/${F.playerStaMax}`;
setBtnVisible('#btn-finish',(F.enemyHP>0&&(F.enemyHP/F.enemyMax)<=0.15));
const healBtn=$q('#btn-heal');
if(healBtn)healBtn.textContent=(F.healCD>0)?'🩹 Heal (CD)':'🩹 Heal';
}
function endCheck(){if(F.playerHP<=0){defeatScreen();return true;}if(F.enemyHP<=0){victoryScreen();return true;}return false;}
function atkBaseFrom(fit){return Math.floor(Math.random()*6)+6+Math.floor(fit/4);}
function enemyDodgeChance(){
let base=clamp(0.25+(Math.max(1,+F.lvl||1)/400),0.25,0.75);
base=clamp(base+((+F.enemyDodgeBias||0.5)-0.5)*0.25,0.15,0.85);
if(F.e.exposed>0)base=base*0.50;
return clamp(base,0.10,0.90);
}
function playerDodgeChance(fit){return clamp(0.10+(fit/200),0.10,0.60);}
function regenCooldownOnly(){if(F.healCD>0)F.healCD-=1;}
function startTurnTick(log){applyDotsAndTick('p',log);applyDotsAndTick('e',log);regenCooldownOnly();}
function enemyActs(log){
if(F.e.stun>0){log.push("😵 Enemy is stunned and skips the turn.");return;}
let action='atk';
const hpPct=F.enemyHP/F.enemyMax;
const roll=Math.random();
if(hpPct<=0.25&&F.enemyBand>0)action='heal';
else if(roll<0.20)action='guard';
else if(roll<0.40)action='heavy';
else action='atk';
if(action==='heal'){const h=Math.floor(F.enemyMax*(0.28+Math.random()*0.04));F.enemyHP=Math.min(F.enemyMax,F.enemyHP+h);F.enemyBand=Math.max(0,(+F.enemyBand||0)-1);showFx("Heal!");log.push(`🩹 Enemy heals: <strong>+${h} HP</strong>.`);return;}
if(action==='guard'){showFx("Guard!");F.e.guard=1;log.push("🛡️ Enemy takes a guarded stance.");return;}
const eFit=Math.max(0,+F.lvl||0);
let dmg=atkBaseFrom(eFit);
if(action==='heavy'){dmg=Math.floor(dmg*2.5);const dChance=enemyDodgeChance();if(Math.random()<dChance){log.push("🛡️ Enemy's heavy blow misses.");return;}showFx("Heavy!");log.push("💥 Enemy goes for a heavy blow!");}else{showFx("Attack!");}
if(F.p.guard>0)dmg=Math.floor(dmg*0.50);
if(F.p.exposed>0)dmg=Math.floor(dmg*1.30);
const fit=Math.max(0,+V.Fitness||0);
const pDodge=playerDodgeChance(fit);
if(action!=='heavy'&&Math.random()<pDodge){showFx("Evade!");log.push("🟦 You evade the enemy hit.");return;}
F.playerHP=Math.max(0,F.playerHP-dmg);
popNumber('#you-pop',`-${dmg}`);
flashHit('#you-card','#you-barbg');
log.push(`🔻 Enemy hits you: <strong>-${dmg} HP</strong>.`);
}
function spendSta(cost){if((+F.playerSta||0)<cost)return false;F.playerSta-=cost;return true;}
function doPlayerAttack(mode){
const fit=Math.max(0,+V.Fitness||0);
let log=[];
let cost=1;
if(mode==='heavy')cost=2;
if(mode==='heal')cost=2;
if(mode==='finish')cost=1;
if(mode==='guard')cost=0;
if(cost>0&&!spendSta(cost)){log.push("⚠️ Not enough stamina.");pushPopup("Fight",log);renderLog();updateHUD();return;}
if(mode==='guard')F.playerSta=clamp((+F.playerSta||0)+1,0,F.playerStaMax);
if(shouldPunch(mode))playPunchSfx();
startTurnTick(log);
if(endCheck()){updateHUD();return;}
if(mode==='guard'){showFx("Guard!");log.push("🛡️ You take a guarded stance. 50% less damage this turn.");F.p.guard=1;enemyActs(log);F.log=log;pushPopup("Fight",log);renderLog();updateHUD();endCheck();return;}
if(mode==='heal'){
if(F.healCD>0){log.push("⏳ Heal is on cooldown.");F.log=log;pushPopup("Fight",log);renderLog();updateHUD();return;}
const med=(V.Inventory&&V.Inventory.medkit)?V.Inventory.medkit:null;
const medQty=(med&&Number.isFinite(+med.qty))?Math.max(0,+med.qty):0;
if(medQty<=0){log.push("❌ You don't have a Medkit.");F.log=log;pushPopup("Fight",log);renderLog();updateHUD();return;}
V.Inventory.medkit.qty=Math.max(0,medQty-1);
const heal=Math.floor(F.playerMax*(0.28+Math.random()*0.04));
F.playerHP=Math.min(F.playerMax,F.playerHP+heal);
F.healCD=1;showFx("Heal!");log.push(`🩹 You heal: <strong>+${heal} HP</strong>.`);
enemyActs(log);F.log=log;pushPopup("Fight",log);renderLog();updateHUD();endCheck();return;
}
if(mode==='finish'){
if((F.enemyHP/F.enemyMax)>0.15){log.push("☠️ Finisher not available yet.");F.log=log;pushPopup("Fight",log);renderLog();updateHUD();return;}
showFx("Finisher!");log.push("☠️ You execute a brutal finisher!");F.enemyHP=0;popNumber('#foe-pop','KO');flashHit('#foe-card','#foe-barbg');F.log=log;pushPopup("Fight",log);renderLog();updateHUD();endCheck();return;
}
nudgeAttack('#you-card');
let dmg=atkBaseFrom(fit);
if(mode==='heavy'){
dmg=Math.floor(dmg*2.5);
showFx("Heavy!");log.push("💥 Heavy attack.");
const dChance=enemyDodgeChance();
if(Math.random()<dChance){showFx("Evaded!");log.push("🛡️ Enemy dodges the heavy blow.");F.log=log;pushPopup("Fight",log);renderLog();enemyActs(log);updateHUD();endCheck();return;}
if(F.p.adr>0){dmg=Math.floor(dmg*1.50);F.p.adr=0;log.push("⚡ Adrenaline boosts your strike.");}
if(F.e.exposed>0)dmg=Math.floor(dmg*1.30);
if(F.e.guard>0)dmg=Math.floor(dmg*0.50);
F.enemyHP=Math.max(0,F.enemyHP-dmg);
popNumber('#foe-pop',`-${dmg}`);flashHit('#foe-card','#foe-barbg');
F.p.adr=1;log.push(`🔺 Heavy hit lands: <strong>-${dmg} HP</strong>. Adrenaline builds.`);
} else {
showFx("Attack!");log.push("🥊 Standard attack.");
if(F.p.adr>0){dmg=Math.floor(dmg*1.50);F.p.adr=0;log.push("⚡ Adrenaline boosts your strike.");}
if(F.e.exposed>0)dmg=Math.floor(dmg*1.30);
if(F.e.guard>0)dmg=Math.floor(dmg*0.50);
const dChance=enemyDodgeChance();
if(Math.random()<dChance){const reduced=Math.floor(dmg*0.40);F.enemyHP=Math.max(0,F.enemyHP-reduced);popNumber('#foe-pop',`-${reduced}`);if(reduced>0)flashHit('#foe-card','#foe-barbg');log.push(`🛡️ Enemy partially dodges. Damage reduced to <strong>-${reduced} HP</strong>.`);}
else{F.enemyHP=Math.max(0,F.enemyHP-dmg);popNumber('#foe-pop',`-${dmg}`);flashHit('#foe-card','#foe-barbg');log.push(`🔺 You hit: <strong>-${dmg} HP</strong>.`);}
}
enemyActs(log);F.log=log;pushPopup("Fight",log);renderLog();updateHUD();endCheck();
}
function bind(sel,fn){const b=$q(sel);if(!b)return;const clone=b.cloneNode(true);b.parentNode.replaceChild(clone,b);clone.addEventListener('click',fn);}
bind('#btn-atk',()=>doPlayerAttack('atk'));
bind('#btn-heavy',()=>doPlayerAttack('heavy'));
bind('#btn-guard',()=>doPlayerAttack('guard'));
bind('#btn-heal',()=>doPlayerAttack('heal'));
bind('#btn-finish',()=>doPlayerAttack('finish'));
setBottom('');
pushPopup("Fight",["Choose an action."]);
updateHUD();
renderLog();
});
})();
<</script>><<sound "music" "music.music" true>><<sound "bg" "bg.city" true>><<passagebg>><img src="assets/img/misc/city/city.webp"/><</passagebg>>
<<InformationUiPopUp>>The man leaves without another word, just throwing a glance back before disappearing into the crowd. The woman catches her breath, one hand on her chest.
<</InformationUiPopUp>>
<<TalkMC "It's okay, he's gone.">>
<<TalkRandom "Woman" "assets/img/character/npc/g8.jpg" "Thank you. Really, thank you. I didn't know what to do.">>
<<TalkRandom "Woman" "assets/img/character/npc/g8.jpg" "I'm so sorry for dragging you into that.">>
<<TalkMC "You have nothing to apologize for.">>
<<InformationUiPopUp>>She exhales once more, glancing in the direction the man disappeared, then turns back to me.
<</InformationUiPopUp>>
<<TalkRandom "Woman" "assets/img/character/npc/g8.jpg" "I just got to the city, I don't know anyone here. I just wanted to walk around, explore the neighborhoods a little, and now I don't dare go back out there alone.">>
<<TalkMC "Not exactly a great welcome.">>
<<TalkRandom "Woman" "assets/img/character/npc/g8.jpg" "No, really not...">>
<<InformationUiPopUp>>She looks at me for a moment, then a slight smile appears, genuine, a little shy.
<</InformationUiPopUp>>
<<TalkRandom "Woman" "assets/img/character/npc/g8.jpg" "Would you... happen to be free? To show me around the city a little? Only if you have time, I don't want to impose.">>
<<InformationUiPopUp>>I think for a few seconds.
<</InformationUiPopUp>><<revealtext "no">><br><<TalkMC "That's nice of you, but I can't, I've got things to do.">>
<<TalkRandom "Woman" "assets/img/character/npc/g8.jpg" "Oh come on, just an hour. You saved me back there, it's the least I can do.">>
<<TalkMC "Really, maybe another time. Take care.">><</revealtext>><<revealtext "leave">><br><<passagebg>><img src="assets/img/story/mayorstory/blackout.webp"/><</passagebg>><<InformationUiPopUp>>I turn my back to her and start walking. I take two steps when something heavy hits me hard from behind. The ground comes up to meet me and I'm out before I even touch it.
<</InformationUiPopUp>><</revealtext>><<revealtext "wakeup">><br><<passagebg>><<if $Time !== 3>><<sound "bg" "bg.park" true>><img src="assets/img/misc/city/park/park.webp"/><<else>><<sound "bg" "bg.parkNight" true>><img src="assets/img/misc/city/park/parknight.webp"/><</if>><</passagebg>><<InformationUiPopUp>>I come back slowly. White light above me, distant voices. I'm lying on a park bench, an ambulance parked nearby, someone leaning over me talking into a radio.
<</InformationUiPopUp>>
<<InformationUiPopUp>>It takes me a few seconds to piece together what happened. I instinctively check my pockets, my phone is there, my wallet too. Nothing was taken, she wasn't after money.
<</InformationUiPopUp>>
<<TalkMC "The file... it's at home. She didn't find what she was looking for.">>
<<InformationUiPopUp>>I sit up slowly, ignoring the paramedic telling me to stay down. My head is spinning but I stay focused.
<</InformationUiPopUp>>
<<TalkMC "Damn, they're really playing dirty... Hargrove is even willing to pull something like this to get the file back...">><</revealtext>><<revealtext "yes">><br><<TalkMC "Why not, I've got time.">>
<<TalkRandom "Woman" "assets/img/character/npc/g8.jpg" "Great, thank you really.">>
<<InformationUiPopUp>>We head back into the city center together. She walks beside me, relaxed, asking questions about the city, about me, about what I do here. I answer without giving too much away.
<</InformationUiPopUp>><</revealtext>><<revealtext "mall">><br><<passagebg>><<sound "bg" "bg.mall" true>><img src="assets/img/misc/city/mall/mall.webp"/><</passagebg>><<InformationUiPopUp>>Since we weren't far, I show her the mall first. She stops in front of shop windows, comments on what she sees, asks my opinion on things that don't matter much.
<</InformationUiPopUp>>
<<TalkRandom "Woman" "assets/img/character/npc/g8.jpg" "It's big, I wasn't expecting that for a city like this.">>
<<TalkMC "It's bigger than it looks from the outside.">><</revealtext>><<revealtext "university">><br><<passagebg>><<sound "bg" "bg.university" true>><img src="assets/img/misc/university/university.webp"/><</passagebg>><<InformationUiPopUp>>Then I show her the university. She looks at the buildings, the students moving around, the notice boards.
<</InformationUiPopUp>>
<<TalkRandom "Woman" "assets/img/character/npc/g8.jpg" "Did you study here?">>
<<TalkMC "For a while.">><</revealtext>><<revealtext "financial">><br><<passagebg>><<sound "bg" "bg.city" true>><img src="assets/img/misc/financialquarter/financialquarter.webp"/><</passagebg>><<InformationUiPopUp>>We head back into town and pass through the financial district. I explain the development planned for the coming years, she listens, nodding. Then, for just a fraction of a second, her gaze locks onto one of the buildings, the Hargrove one, a little too focused, a slight hesitation before she responds.
<</InformationUiPopUp>>
<<TalkRandom "Woman" "assets/img/character/npc/g8.jpg" "It's... quite a construction site.">>
<<TalkMC "Yeah, there's a lot of buildings going up around here, the district is still pretty new.">>
<<TalkRandom "Woman" "assets/img/character/npc/g8.jpg" "I can imagine.">>
<<InformationUiPopUp>>She looks away fairly quickly and changes the subject.
<</InformationUiPopUp>><</revealtext>><<revealtext "park">><br><<passagebg>><<sound "bg" "bg.park" true>><img src="assets/img/misc/city/park/park.webp"/><</passagebg>><<InformationUiPopUp>>I decide to take her to the park to finish. The sunlight is starting to fade, the air is softer, we walk along a tree-lined path. Something in her attitude has shifted since earlier, she moves a little closer, her shoulders brushing mine as we walk, her hand grazing mine once, then again, without pushing it. A clear interest, gradual, gentle.
<</InformationUiPopUp>>
<<TalkRandom "Woman" "assets/img/character/npc/g8.jpg" "I never would have seen all of this on my own, thank you.">>
<<TalkMC "It's a city that rewards exploring.">>
<<TalkRandom "Woman" "assets/img/character/npc/g8.jpg" "With the right person especially.">>
<<InformationUiPopUp>>She smiles as she says it, not looking away. Evening is starting to fall.
<</InformationUiPopUp>>
<<TalkMC "Do you have somewhere to sleep tonight?">>
<<TalkRandom "Woman" "assets/img/character/npc/g8.jpg" "Not really, no.">>
<<TalkMC "I know a place if you'd like.">><</revealtext>>
<div class="BottomUiBarCustom">
<<BottomButton "Story">><<revealbtn "yes" "✅ Yes" "" "choice" "mall" true>><</revealbtn>><<revealbtn "mall" "➡️ Continue" "" "mall" "university" false>><</revealbtn>><<revealbtn "university" "➡️ Continue" "" "university" "financial" false>><</revealbtn>><<revealbtn "financial" "➡️ Continue" "" "financial" "park" false>><</revealbtn>><<revealbtn "park" "➡️ Continue" "moveBtnYes" "park" "" false>><</revealbtn>><<revealbtn "no" "❌ No" "" "choice" "leave" true>><</revealbtn>><<revealbtn "leave" "➡️ Leave" "" "leave" "wakeup" false>><<sound "sfx" "sfx.punch" false>><</revealbtn>><<revealbtn "wakeup" "😴 Wake up" "moveBtnNo" "wakeup" "" false>><</revealbtn>><</BottomButton>>
<<BottomButton "Story" "moveBtnNo">><<link "➡️ Leave">><<goto "Park">><<set $Time++>><<set $MayorStoryInfo7 = true>><<set $MayorStoryInfo8 = true>><</link>><</BottomButton>><<BottomButton "Story" "moveBtnYes">><<link "➡️ Continue">><<goto "MayorStory13">><</link>><</BottomButton>>
</div><<sound "music" "music.music" true>><<sound "bg" "bg.empty" true>><<passagebg>><img src="assets/img/misc/home/mcbedroomnight.webp"><</passagebg>>
<<InformationUiPopUp>>We arrive at night. I take her straight to my bedroom. She walks in, turns to face me, and without a word starts undressing slowly, her eyes on mine, removing each piece of clothing with deliberate slowness, savoring every second of the gaze she holds.
<</InformationUiPopUp>>
<<TalkRandom "Woman" "assets/img/character/npc/g8.jpg" "You're looking at me like you've never seen a woman undress before.">>
<<TalkMC "I'm just looking at what's worth looking at.">>
<<InformationUiPopUp>>She smiles and goes to lie down on the bed.
<</InformationUiPopUp>>
<<InformationUiPopUp>>She's lying on her stomach, ass raised, and slowly slides a finger under the edge of her underwear at her pussy, pulling the fabric to the side to expose everything. She looks back at me over her shoulder.
<</InformationUiPopUp>>
<video src="assets/img/story/mayorstory/woman/01.mp4"/>
<<TalkRandom "Woman" "assets/img/character/npc/g8.jpg" "Coming?">>
<<InformationUiPopUp>>I move toward the bed. She straightens up and reaches for my trousers.
<</InformationUiPopUp>>
<video src="assets/img/story/mayorstory/woman/02.mp4"/>
<<TalkRandom "Woman" "assets/img/character/npc/g8.jpg" "<em>Mmh... glrk... mmh...</em>">>
<<TalkMC "Incredible, keep going like that.">>
<<InformationUiPopUp>>I put a hand on her ass, slapping it several times, then slide my fingers under the edge of her underwear and pull the fabric to the side, exposing her pussy and ass. She moans against my cock without stopping.
<</InformationUiPopUp>>
<video src="assets/img/story/mayorstory/woman/03.mp4"/>
<<TalkRandom "Woman" "assets/img/character/npc/g8.jpg" "<em>Mmh... ghlk... mmh...</em>">>
<<InformationUiPopUp>>She straightens up onto her knees and slowly unclasps her bra, letting it slide down her arms before setting it aside. Then she lies back down. I sit on her stomach and take her tits in my hands, touching them gently, pressing her nipples between my fingers.
<</InformationUiPopUp>>
<video src="assets/img/story/mayorstory/woman/04.mp4"/>
<<TalkRandom "Woman" "assets/img/character/npc/g8.jpg" "Ah... gently...">>
<<TalkMC "Like this?">>
<<TalkRandom "Woman" "assets/img/character/npc/g8.jpg" "Yes... exactly like that.">>
<<InformationUiPopUp>>She presses her tits together with both hands. I slide my cock between them and start moving slowly. She looks down to watch, her breathing picking up.
<</InformationUiPopUp>>
<video src="assets/img/story/mayorstory/woman/05.mp4"/>
<<TalkRandom "Woman" "assets/img/character/npc/g8.jpg" "<em>Ah... mmh...</em>">>
<<InformationUiPopUp>>I reposition myself and enter her pussy slowly. She exhales hard, her hands running over her own tits and down her stomach, then her arms sliding up along the bed above her head.
<</InformationUiPopUp>>
<video src="assets/img/story/mayorstory/woman/06.mp4"/>
<<TalkRandom "Woman" "assets/img/character/npc/g8.jpg" "<em>Ah... yes... like that...</em>">>
<<TalkMC "You like that.">>
<<TalkRandom "Woman" "assets/img/character/npc/g8.jpg" "Yes... keep going please.">>
<<InformationUiPopUp>>I pick up the pace. My hand moves up to her tits first, then down to her pussy, rubbing her clit while I fuck her, feeling every shiver that runs through her body.
<</InformationUiPopUp>>
<video src="assets/img/story/mayorstory/woman/07.mp4"/>
<<TalkRandom "Woman" "assets/img/character/npc/g8.jpg" "<em>Ah... fuck... yes...</em>">>
<<InformationUiPopUp>>After a while, I lie down on my back and she climbs on top of me, facing away, lowering herself onto my cock slowly, finding the angle before starting to move.
<</InformationUiPopUp>>
<video src="assets/img/story/mayorstory/woman/08.mp4"/>
<<TalkRandom "Woman" "assets/img/character/npc/g8.jpg" "<em>Ah... mmh... it's so deep like this...</em>">>
<<InformationUiPopUp>>She turns around without pulling off, now facing me, hands resting behind her, picking the rhythm back up.
<</InformationUiPopUp>>
<video src="assets/img/story/mayorstory/woman/09.mp4"/>
<<TalkRandom "Woman" "assets/img/character/npc/g8.jpg" "<em>Ah... yes... yes...</em>">>
<<InformationUiPopUp>>I turn her onto all fours and take her from behind, hands firmly on her hips, setting my own rhythm.
<</InformationUiPopUp>>
<video src="assets/img/story/mayorstory/woman/10.mp4"/>
<<TalkRandom "Woman" "assets/img/character/npc/g8.jpg" "<em>Ah... fuck... more...</em>">>
<<TalkMC "Stay like that.">>
<<TalkRandom "Woman" "assets/img/character/npc/g8.jpg" "Yes... I'm not moving.">>
<video src="assets/img/story/mayorstory/woman/11.mp4"/>
<<TalkRandom "Woman" "assets/img/character/npc/g8.jpg" "<em>Ah... ah... yes... yes...</em>">>
<<InformationUiPopUp>>I press down on her back, she ends up lying flat on her stomach and I spread her ass with my hand while fucking her pussy, pushing deep.
<</InformationUiPopUp>>
<video src="assets/img/story/mayorstory/woman/12.mp4"/>
<<TalkRandom "Woman" "assets/img/character/npc/g8.jpg" "<em>Mmh... ah... it feels so good...</em>">>
<<InformationUiPopUp>>She turns onto her back. I take her again, the rhythm building gradually. She grips the sheets, eyes half-closed, breathing shorter and shorter. I end up coming inside her, staying still for a moment, before pulling out slowly.
<</InformationUiPopUp>>
<video src="assets/img/story/mayorstory/woman/13.mp4"/>
<<TalkRandom "Woman" "assets/img/character/npc/g8.jpg" "<em>Aaah... mmmh...</em>">>
<<TalkRandom "Woman" "assets/img/character/npc/g8.jpg" "Fuck, that was so good.">>
<<InformationUiPopUp>>She stays lying there, catching her breath, eyes on the ceiling. I lie down beside her. The room goes quiet again while the night continues outside.
<</InformationUiPopUp>>
<<revealtext "wakeup">><<passagebg>><img src="assets/img/story/mayorstory/mcbedroom.webp"/><</passagebg>><<InformationUiPopUp>>The next morning, I open my eyes slowly. Something feels off immediately, my room is in disarray, drawers open, things moved around. But no sign of her.
<</InformationUiPopUp>>
<<TalkMC "Oh shit...">>
<<InformationUiPopUp>>I get up quickly and go straight to check my hiding spot.
<</InformationUiPopUp>>
<<TalkMC "...">>
<<InformationUiPopUp>>The file is there, untouched. She didn't find anything. I sit down on the edge of the bed and stay there for a moment, staring into nothing.
<</InformationUiPopUp>>
<<TalkMC "She was working for them... The whole day she played me. The guy following her, the fight, the tour, and last night, all of it was staged to get me to let my guard down.">>
<<InformationUiPopUp>>I look around the room. The search was clearly rushed, maybe she was afraid I'd wake up while she was going through my things.
<</InformationUiPopUp>>
<<TalkMC "They're willing to go that far to get this file back. And since they didn't manage to get it, they're obviously going to try again...">><</revealtext>>
<div class="BottomUiBarCustom">
<<BottomButton "Story">><<revealbtn "wakeup" "🥱 Wake up" "moveBtn" "" "" true>><</revealbtn>><</BottomButton>>
<<BottomButton "Story" "moveBtn">><<link "🧹 Put everything away">><<goto "MCBedroom">><<set $Energy = $EnergyMax>><<set $PsychicPower = $PsychicPowerMax>><<if $Heal < $HealMax>><<set $Heal += 25>><</if>><<if $Stress > $StressMin>><<set $Stress -= 2>><</if>><<set $SpectatorsThePit = random(25,50)>><<set $SpectatorsThePit += 25>><<set $Day++>><<set $Time = 0>><<set $Hour = 0>><<set $TravelPerTime = 0>><<set $ShowerDayTime = false, $FitnessDayTime = false, $MedidationDayTime = false>><<set $AutoSaveCheck = true>>
<<script>>
(function(){
var V = State.variables;
if(!V.SpycamUnlocked) V.SpycamUnlocked = {};
if(V.SpycamLastUnlockDay === V.Day) return;
V.SpycamUnlockedToday = 0;
var activeCams = [];
for(var ck in V.Spycam){ if(V.Spycam[ck]) activeCams.push(ck); }
if(activeCams.length === 0){
V.SpycamLastUnlockDay = V.Day;
return;
}
var storageLvl = V.PCstockage.img;
var maxStorage = 5 + Math.max(0, storageLvl - 1) * 5;
maxStorage = Math.min(15, maxStorage);
if(storageLvl < 1) maxStorage = 5;
var shuffled = activeCams.slice();
for(var i = shuffled.length - 1; i > 0; i--){
var j = Math.floor(Math.random() * (i + 1));
var tmp = shuffled[i]; shuffled[i] = shuffled[j]; shuffled[j] = tmp;
}
var unlockedToday = 0;
for(var k = 0; k < shuffled.length; k++){
if(unlockedToday >= 2) break;
var camK = shuffled[k];
var totalCount = 0;
for(var c2 in V.SpycamUnlocked){
if(V.Spycam[c2]) totalCount += (V.SpycamUnlocked[c2] || []).length;
}
if(totalCount >= maxStorage) break;
var camMax = (setup.SpycamMaxImages && setup.SpycamMaxImages[camK]) || 0;
if(camMax < 1) continue;
if(Math.random() < 0.5){
var alreadyOwned = (V.SpycamUnlocked[camK] || []).slice();
var candidates = [];
for(var n = 1; n <= camMax; n++){
if(alreadyOwned.indexOf(n) === -1) candidates.push(n);
}
if(candidates.length > 0){
var pickedNum = candidates[Math.floor(Math.random() * candidates.length)];
if(!V.SpycamUnlocked[camK]) V.SpycamUnlocked[camK] = [];
V.SpycamUnlocked[camK].push(pickedNum);
unlockedToday++;
V.SpycamUnlockedToday = (V.SpycamUnlockedToday || 0) + 1;
}
}
}
V.SpycamLastUnlockDay = V.Day;
})();
<</script>><<set $MayorStoryInfo7 = true>><<set $MayorStoryInfo8 = true>><</link>><</BottomButton>>
</div><<sound "music" "music.music" true>><<sound "bg" "bg.empty" true>><<passagebg>><<if $Time !== 3>><img src="assets/img/misc/oldtown/traphouse/traphouse.webp"/><<else>><img src="assets/img/misc/oldtown/traphouse/traphousenight.webp"/><</if>><</passagebg>><<InformationUiPopUp>>I head to the TrapHouse. Inside everything looks the same as usual, nothing out of the ordinary on the surface. But once upstairs, when I walk into the room to talk to W., I can tell something has changed. W. is there, sitting on the edge of a table, arms crossed, watching me come in without moving, without smiling, without the usual word for a customer walking through the door.
<</InformationUiPopUp>>
<<TalkRandom "W. <em>(Dealer)</em>" "assets/img/character/npc/b3.jpg" "Close the door behind you.">>
<<InformationUiPopUp>>I close the door and turn back toward him. He says nothing for a few seconds, sizing me up like he's picking his words.
<</InformationUiPopUp>>
<<TalkMC "What's going on?">>
<<TalkRandom "W. <em>(Dealer)</em>" "assets/img/character/npc/b3.jpg" "Some guys came by here, not long ago. Two people I'd never seen before, not from the neighborhood, not the type to hang around here without a reason, and they offered me a job.">>
<<TalkMC "A job...?">>
<<TalkRandom "W. <em>(Dealer)</em>" "assets/img/character/npc/b3.jpg" "Grab you. Bring you to them, alive, they specified, which means they want to talk to you, or make you regret something, I don't really know, and honestly I don't give a shit about that part. They put money on the table. A lot of money.">>
<<InformationUiPopUp>>I stay calm on the outside but I can feel things tightening. He keeps going before I have time to respond.
<</InformationUiPopUp>>
<<TalkRandom "W. <em>(Dealer)</em>" "assets/img/character/npc/b3.jpg" "I turned it down. And I'm going to be straight with you, don't go thinking I like you or whatever, you're just a customer. The reason I said no is that I can spot something rotten from miles away, and this kind of job stinks like a trap. It draws attention, it draws questions, and at some point it draws the police. I sell drugs. Quietly. Without making waves. I absolutely don't want my business turning into the backdrop for someone else's mess.">>
<<TalkMC "...">>
<<TalkRandom "W. <em>(Dealer)</em>" "assets/img/character/npc/b3.jpg" "But... you see, there's something else that's bothering me.">>
<<InformationUiPopUp>>He gets up, takes a step toward me and lowers his voice, even though we're alone in the room.
<</InformationUiPopUp>>
<<TalkRandom "W. <em>(Dealer)</em>" "assets/img/character/npc/b3.jpg" "What's bugging me is the timing. Guys nobody around here has ever seen show up, to ask ME to grab you, and it lands right around the same time you came here buying equipment to pull a job. You get what I'm saying? In this business, that kind of coincidence isn't called a coincidence.">>
<<TalkMC "So you're thinking there's a connection?">>
<<TalkRandom "W. <em>(Dealer)</em>" "assets/img/character/npc/b3.jpg" "I'm not thinking anything. I never make assumptions about other people's business, that's a rule I've kept for a long time. But I'm telling you what I observed, and you do whatever you want with it.">>
<<InformationUiPopUp>>He goes back to sitting on the edge of his table, arms crossed again, closed off.
<</InformationUiPopUp>>
<<TalkRandom "W. <em>(Dealer)</em>" "assets/img/character/npc/b3.jpg" "What I do know is that until your problem is sorted, I don't want to see you here. Those guys know you've already been through my place. If they come back and you're here, things are going to go sideways fast, and that becomes my problem too. And that's something I can't afford.">>
<<TalkMC "That's fair.">>
<<TalkRandom "W. <em>(Dealer)</em>" "assets/img/character/npc/b3.jpg" "Sort out whatever you've got to sort out. Once it's clean, you come back. Until then, you don't know this place, and you don't know me.">>
<<InformationUiPopUp>>I stay quiet for a second. I'm annoyed, not at him, at the situation. He stayed straight with me when he could have played it differently. That's not nothing.
<</InformationUiPopUp>>
<<TalkMC "Alright, understood. Thanks anyway for turning it down.">>
<<TalkRandom "W. <em>(Dealer)</em>" "assets/img/character/npc/b3.jpg" "Don't flatter yourself, it was purely in my own interest.">>
<<InformationUiPopUp>>I nod and walk out of the building. The air outside is the same as when I came in, but something has shifted in the way I'm breathing it.
<</InformationUiPopUp>>
<<TalkMC "They tried to have someone outside the whole thing grab me. They're really starting to lose patience.">>
<div class="BottomUiBarCustom">
<<BottomButton "Story">><<link "🚪 Exit">><<goto "MayorStory15">><</link>><</BottomButton>>
</div><<sound "music" "music.music" true>><<passagebg>><<if $Time !== 3>><<sound "bg" "bg.city" true>><img src="assets/img/misc/oldtown/oldtown.webp"/><<else>><<sound "bg" "bg.cityNight" true>><img src="assets/img/misc/oldtown/oldtownnight.webp"/><</if>><</passagebg>><<InformationUiPopUp>>I step out of the building and make my way through the Oldtown. The street is quiet, the same worn-down facades, the same narrow alleys. I walk with my mind elsewhere, thinking about what comes next, what needs to happen and in what order.
<</InformationUiPopUp>>
<<TalkMC "I need to speed things up with the mayor... The longer I wait, the more they're going to keep busting my balls and doing everything they can to get their hands on me.">>
<<InformationUiPopUp>>Turning into an alley, two figures appear out of nowhere. Fast, coordinated. One blocks me from the front, the other grabs me from behind before I have time to react. They drag me into the alley, out of sight, in a matter of seconds.
<</InformationUiPopUp>>
<<TalkMC "What the fuck, get off me you sons of bitches!">>
<<TalkRandom "Strange Man" "assets/img/character/npc/b2.jpg" "Shut it! We're not going to hurt you if you cooperate.">>
<<TalkMC "Like I'd believe that!">>
<<TalkRandom "Strange Man" "assets/img/character/npc/b3.jpg" "Stop yelling it won't do anything! Just give us the file, we know you have it. Hand it over and everyone goes home.">>
<<TalkMC "I don't know what the hell you're talking about!">>
<<TalkRandom "Strange Man" "assets/img/character/npc/b2.jpg" "Tss... wrong answer.">>
<<InformationUiPopUp>>The first one raises his fist. I don't wait for it to come down and raise mine.
<</InformationUiPopUp>>
<<InformationUiPopUp "⚠️ Important ⚠️" "#e65763">>It is advised to save here, you can lose the game during this fight!
<</InformationUiPopUp>>
<div class="BottomUiBarCustom">
<<BottomButton "Action">><<link "💥 Fight">><<goto "MayorStory16">><</link>><</BottomButton>>
</div><<set $Fight = {
type: "Man",
lvl: 55,
playerMax: $HealMax,
playerHP: $Heal,
enemyMax: 125,
enemyHP: 125,
playerBand: 0,
enemyBand: 1,
playerStaMax: 5,
playerSta: 5,
healCD: 0,
log: [],
p: {},
e: {},
enemyDodgeBias: 0.55
}>><<sound "music" "music.fight" true>><<passagebg>><<if $Time !== 3>><<sound "bg" "bg.city" true>><img src="assets/img/misc/oldtown/oldtown.webp"/><<else>><<sound "bg" "bg.cityNight" true>><img src="assets/img/misc/oldtown/oldtownnight.webp"/><</if>><</passagebg>><div id="fight-tip" style="display:none;"></div><div class="fight-ui" style="max-width:960px;margin:auto;"><div id="foe-card" class="foes card" style="display:flex;gap:12px;justify-content:space-between;align-items:center;padding:10px;border:1px solid #444;border-radius:10px;margin-bottom:10px;"><div style="width:100%;"><p style="margin:0;"><strong>Enemy:</strong> <span id="foe-type"></span> (Fitness <span id="foe-lvl"></span>) <span id="foe-states" class="states"></span></p><div class="hp-bar-bg" id="foe-barbg"><div id="foe-bar" class="hp-bar"></div><div class="pop-layer" id="foe-pop"></div></div><p style="margin:4px 0 0 0;">HP <span id="foe-hp"></span> / <span id="foe-max"></span> · 🩹 <span id="foe-band"></span></p></div></div><div id="you-card" class="you card" style="display:flex;gap:12px;justify-content:space-between;align-items:center;padding:10px;border:1px solid #444;border-radius:10px;margin-bottom:14px;"><div style="width:100%;"><p style="margin:0;"><strong>You</strong> (Fitness <span id="player-fit"></span>) <span id="you-states" class="states"></span></p><div class="hp-bar-bg" id="you-barbg"><div id="you-bar" class="hp-bar"></div><div class="pop-layer" id="you-pop"></div></div><div class="sta-row"><span class="sta-label">Stamina</span><div class="sta-bg"><div id="you-sta" class="sta-bar"></div></div><span id="you-sta-txt" class="sta-txt"></span></div><p style="margin:4px 0 0 0;">HP <span id="you-hp"></span> / <span id="you-max"></span> · 🩹 <span id="you-band"></span></p></div></div><div id="fight-actions" style="display:flex;gap:10px;flex-wrap:wrap;margin-bottom:10px;"><button id="btn-atk" type="button" data-tip="Standard attack. Deals solid damage based on your Fitness. Cost: 1 stamina.">🥊 Attack</button><button id="btn-heavy" type="button" data-tip="Heavy attack. Deals 2.5x damage based on Fitness, but costs 2 stamina and misses more often.">💥 Heavy</button><button id="btn-guard" type="button" data-tip="Guard. You take 50% less damage this turn. Cost: 0 stamina. Gain: +1 stamina.">🛡️ Guard</button><button id="btn-heal" type="button" data-tip="Heal using a Medkit. Cooldown: every other turn. Cost: 2 stamina. Requires: 1 Medkit.">🩹 Heal</button><button id="btn-finish" type="button" style="display:none;" data-tip="Finisher. Available when enemy HP is 15% or less. Ends the fight instantly. Cost: 1 stamina.">☠️ Finisher</button></div><div id="fight-popups"></div><div id="fight-stage"></div></div><div class="BottomUiBarCustom"><span style="display:contents;" id="fight-actionsbar"></span></div><style>#fight-tip{position:fixed;z-index:99999;display:none;max-width:280px;padding:8px 10px;border:1px solid rgba(255,255,255,.25);border-radius:10px;background:rgba(10,10,10,.92);backdrop-filter:blur(3px);color:#fff;font-size:.9rem;line-height:1.25;pointer-events:none;box-shadow:0 6px 18px rgba(0,0,0,.35);} .fight-ui p{line-height:1.3;} .fight-ui .card{background:rgba(255,255,255,0.03);} #fight-actions button{padding:8px 12px;border:1px solid #666;border-radius:8px;background:transparent;cursor:pointer;color:#fff;} #fight-actions button:hover{background:rgba(255,255,255,0.06);} #fight-actions button:disabled{opacity:.45;cursor:not-allowed;} .hp-bar-bg{position:relative;height:14px;background:#222;border-radius:7px;overflow:hidden;margin-top:6px;} .hp-bar{height:100%;width:100%;transition:width 250ms ease-in-out,background 250ms linear;} .pop-layer{position:absolute;inset:0;pointer-events:none;overflow:visible;} .dmg-pop{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);font-weight:800;opacity:0;animation:popFloat 650ms ease-out forwards;text-shadow:0 1px 0 rgba(0,0,0,.55);} @keyframes popFloat{0%{opacity:0;transform:translate(-50%,-40%) scale(.9);}15%{opacity:1;}100%{opacity:0;transform:translate(-50%,-140%) scale(1.05);}} .hitFlash{animation:hitFlash 220ms ease-out;} @keyframes hitFlash{0%{filter:none;}40%{filter:brightness(1.35);}100%{filter:none;}} .shake{animation:shake 180ms ease-in-out;} @keyframes shake{0%{transform:translateX(0);}25%{transform:translateX(-3px);}50%{transform:translateX(3px);}75%{transform:translateX(-2px);}100%{transform:translateX(0);}} .attackNudge{animation:attackNudge 160ms ease-in-out;} @keyframes attackNudge{0%{transform:translateX(0);}50%{transform:translateX(3px);}100%{transform:translateX(0);}} .states{font-size:.85rem;opacity:.9;margin-left:8px;} .statePill{display:inline-block;padding:1px 6px;border:1px solid rgba(255,255,255,.25);border-radius:999px;margin-left:6px;font-size:.78rem;} .sta-row{display:flex;align-items:center;gap:8px;margin-top:8px;} .sta-label{font-size:.85rem;opacity:.9;} .sta-bg{height:10px;width:160px;border-radius:6px;background:#222;overflow:hidden;} .sta-bar{height:100%;width:100%;transition:width 200ms ease-in-out;background:#5090e2;} .sta-txt{font-size:.85rem;opacity:.9;min-width:34px;text-align:right;} .fxBadge{display:inline-block;margin-top:6px;font-weight:900;letter-spacing:.3px;opacity:0;animation:fxBadge 650ms ease-out forwards;} @keyframes fxBadge{0%{opacity:0;transform:translateY(2px) scale(.98);}20%{opacity:1;}100%{opacity:0;transform:translateY(-10px) scale(1.02);}}</style>
<<script>>
(function(){
$(document).on(':passagedisplay',function(ev){
if(!ev||!ev.passage||ev.passage.title!=='MayorStory16')return;
const V=State.variables;
const F=V.Fight||(V.Fight={type:"?",lvl:1,playerMax:100,enemyMax:100,playerHP:100,enemyHP:100,playerBand:0,enemyBand:1,playerStaMax:5,playerSta:5,healCD:0,log:[],p:{},e:{}});
const $q=(sel)=>document.querySelector(sel);
function playPunchSfx(){try{if(!window.setup||!setup.AudioMixer)return;setup.AudioMixer.playPlaylist("sfx","sfx.punch",false,{fadeInMs:0,fadeOutMs:0});}catch(e){}}
function shouldPunch(mode){return mode==='atk'||mode==='heavy'||mode==='finish';}
const tip=$q('#fight-tip');
function tipShow(text){if(!tip)return;tip.textContent=text;tip.style.display='block';}
function tipHide(){if(!tip)return;tip.style.display='none';}
function tipMove(e){if(!tip||tip.style.display==='none')return;const pad=14;let x=e.clientX+pad,y=e.clientY+pad;const r=tip.getBoundingClientRect();if(x+r.width>window.innerWidth-8)x=e.clientX-r.width-pad;if(y+r.height>window.innerHeight-8)y=e.clientY-r.height-pad;tip.style.left=x+'px';tip.style.top=y+'px';}
function bindTips(root){if(!root)return;root.addEventListener('mousemove',tipMove,{passive:true});root.addEventListener('mouseover',function(e){const el=e.target&&e.target.closest?e.target.closest('[data-tip]'):null;if(!el)return;const t=el.getAttribute('data-tip');if(t&&t.trim())tipShow(t.trim());});root.addEventListener('mouseout',function(e){const el=e.target&&e.target.closest?e.target.closest('[data-tip]'):null;if(!el)return;const to=e.relatedTarget&&e.relatedTarget.closest?e.relatedTarget.closest('[data-tip]'):null;if(to===el)return;tipHide();});}
bindTips($q('.fight-ui'));
function pct(v,max){return Math.max(0,Math.min(100,Math.floor((v/max)*100)));}
function clamp(n,min,max){return(n<min?min:(n>max?max:n));}
function barColor(percent){if(percent>70)return"#2ecc71";if(percent>35)return"#f1c40f";return"#e74c3c";}
function setActionsEnabled(enabled){['#btn-atk','#btn-heavy','#btn-guard','#btn-heal','#btn-finish'].forEach(sel=>{const b=$q(sel);if(b)b.disabled=!enabled;});}
function setBtnVisible(sel,visible){const b=$q(sel);if(!b)return;b.style.display=visible?'':'none';}
function popNumber(target,text){const layer=$q(target);if(!layer)return;const el=document.createElement('div');el.className='dmg-pop';el.textContent=text;layer.appendChild(el);setTimeout(()=>{try{el.remove();}catch(e){}},700);}
function flashHit(cardSel,barBgSel){const c=$q(cardSel),b=$q(barBgSel);if(c){c.classList.remove('shake');c.classList.add('shake');setTimeout(()=>c.classList.remove('shake'),220);}if(b){b.classList.remove('hitFlash');b.classList.add('hitFlash');setTimeout(()=>b.classList.remove('hitFlash'),260);}}
function nudgeAttack(cardSel){const c=$q(cardSel);if(!c)return;c.classList.remove('attackNudge');c.classList.add('attackNudge');setTimeout(()=>c.classList.remove('attackNudge'),220);}
function showFx(text){const box=$q('#fight-stage');if(!box)return;const el=document.createElement('div');el.className='fxBadge';el.textContent=text;box.prepend(el);setTimeout(()=>{try{el.remove();}catch(e){}},700);}
function renderLog(){const box=$q('#fight-stage');if(!box)return;box.innerHTML='';}
function setBottom(wiki){const slot=$q('#fight-actionsbar');if(!slot)return;try{slot.innerHTML='';slot.appendChild(Wikifier.wikifyEval(String(wiki||'')));}catch(e){}}
function pushPopup(title,lines){const box=$q('#fight-popups');if(!box)return;try{box.innerHTML='';const t=String(title||'Info').replace(/"/g,'"');const arr=Array.isArray(lines)?lines:((lines!=null)?[String(lines)]:[]);const html=arr.filter(Boolean).map(s=>String(s)).join('<br>');box.appendChild(Wikifier.wikifyEval('<<InformationUiPopUp "'+t+'">>'+html+'<</InformationUiPopUp>>'));}catch(e){}}
function victoryScreen(){
const box=$q('#fight-stage');if(!box)return;
setActionsEnabled(false);box.innerHTML='';
pushPopup("Victory",["🏆 Victory! The enemy is defeated."]);
setBottom('<<BottomButton "Move">><<link "💥 Fight the second man">><<goto "MayorStory17">><</link>><</BottomButton>>');
}
function defeatScreen(){
const box=$q('#fight-stage');if(!box)return;
setActionsEnabled(false);box.innerHTML='';
pushPopup("Defeat",["💥 You are knocked out."]);
setBottom('<<BottomButton "Move">><<link "Continue">><<goto "End.Fight">><</link>><</BottomButton>>');
}
function applyDotsAndTick(sideKey,log){
const S=(sideKey==='p')?F.p:F.e;
if(S.bleed&&S.bleed>0){const dmg=Math.max(1,+S.bleedDmg||2);if(sideKey==='p'){F.playerHP=Math.max(0,F.playerHP-dmg);popNumber('#you-pop',`-${dmg}`);flashHit('#you-card','#you-barbg');log.push(`🩸 Bleeding tick on you: <strong>-${dmg} HP</strong>.`);}else{F.enemyHP=Math.max(0,F.enemyHP-dmg);popNumber('#foe-pop',`-${dmg}`);flashHit('#foe-card','#foe-barbg');log.push(`🩸 Bleeding tick on enemy: <strong>-${dmg} HP</strong>.`);}S.bleed-=1;}
if(S.guard&&S.guard>0)S.guard-=1;
if(S.exposed&&S.exposed>0)S.exposed-=1;
if(S.adr&&S.adr>0)S.adr-=1;
if(S.stun&&S.stun>0)S.stun-=1;
if(sideKey==='p'){V.Heal=F.playerHP;}
}
function pill(label,tipText){return`<span class="statePill" data-tip="${String(tipText).replace(/"/g,'"')}">${label}</span>`;}
function statePills(S){
let out=[];
if(S.stun>0)out.push(pill(`Stunned ${S.stun}`,"Stunned: skips the next turn."));
if(S.bleed>0)out.push(pill(`Bleeding ${S.bleed}`,"Bleeding: takes damage at the start of each turn."));
if(S.guard>0)out.push(pill("Guarded","Guarded: takes 50% less damage this turn."));
if(S.exposed>0)out.push(pill("Exposed","Exposed: takes 30% more damage."));
if(S.adr>0)out.push(pill("Adrenaline","Adrenaline: your next hit deals 50% more damage."));
return out.join('');
}
function updateHUD(){
const foeType=$q('#foe-type'),foeLvl=$q('#foe-lvl'),foeHP=$q('#foe-hp'),foeMax=$q('#foe-max'),foeBand=$q('#foe-band'),foeBar=$q('#foe-bar'),foeStates=$q('#foe-states');
const youFit=$q('#player-fit'),youHP=$q('#you-hp'),youMax=$q('#you-max'),youBand=$q('#you-band'),youBar=$q('#you-bar'),youStates=$q('#you-states');
const youSta=$q('#you-sta'),youStaTxt=$q('#you-sta-txt');
if(!foeType||!foeLvl||!foeHP||!foeMax||!foeBand||!foeBar||!youFit||!youHP||!youMax||!youBand||!youBar)return;
foeType.textContent=F.type;foeLvl.textContent=F.lvl;foeHP.textContent=F.enemyHP;foeMax.textContent=F.enemyMax;foeBand.textContent=F.enemyBand;
const foePct=pct(F.enemyHP,F.enemyMax);foeBar.style.width=foePct+'%';foeBar.style.background=barColor(foePct);
if(foeStates)foeStates.innerHTML=statePills(F.e);
const fit=Math.max(0,+V.Fitness||0);
youFit.textContent=fit;youHP.textContent=F.playerHP;youMax.textContent=F.playerMax;
const medQty=(V.Inventory&&V.Inventory.medkit&&Number.isFinite(+V.Inventory.medkit.qty))?Math.max(0,+V.Inventory.medkit.qty):0;
youBand.textContent=medQty;
const youPct=pct(F.playerHP,F.playerMax);youBar.style.width=youPct+'%';youBar.style.background=barColor(youPct);
if(youStates)youStates.innerHTML=statePills(F.p);
const staPct=pct(F.playerSta,F.playerStaMax);
if(youSta)youSta.style.width=staPct+'%';
if(youStaTxt)youStaTxt.textContent=`${F.playerSta}/${F.playerStaMax}`;
setBtnVisible('#btn-finish',(F.enemyHP>0&&(F.enemyHP/F.enemyMax)<=0.15));
const healBtn=$q('#btn-heal');
if(healBtn)healBtn.textContent=(F.healCD>0)?'🩹 Heal (CD)':'🩹 Heal';
}
function endCheck(){if(F.playerHP<=0){defeatScreen();return true;}if(F.enemyHP<=0){victoryScreen();return true;}return false;}
function atkBaseFrom(fit){return Math.floor(Math.random()*6)+6+Math.floor(fit/4);}
function enemyDodgeChance(){
let base=clamp(0.25+(Math.max(1,+F.lvl||1)/400),0.25,0.75);
base=clamp(base+((+F.enemyDodgeBias||0.5)-0.5)*0.25,0.15,0.85);
if(F.e.exposed>0)base=base*0.50;
return clamp(base,0.10,0.90);
}
function playerDodgeChance(fit){return clamp(0.10+(fit/200),0.10,0.60);}
function regenCooldownOnly(){if(F.healCD>0)F.healCD-=1;}
function startTurnTick(log){applyDotsAndTick('p',log);applyDotsAndTick('e',log);regenCooldownOnly();}
function enemyActs(log){
if(F.e.stun>0){log.push("😵 Enemy is stunned and skips the turn.");return;}
let action='atk';
const hpPct=F.enemyHP/F.enemyMax;
const roll=Math.random();
if(hpPct<=0.25&&F.enemyBand>0)action='heal';
else if(roll<0.20)action='guard';
else if(roll<0.40)action='heavy';
else action='atk';
if(action==='heal'){const h=Math.floor(F.enemyMax*(0.28+Math.random()*0.04));F.enemyHP=Math.min(F.enemyMax,F.enemyHP+h);F.enemyBand=Math.max(0,(+F.enemyBand||0)-1);showFx("Heal!");log.push(`🩹 Enemy heals: <strong>+${h} HP</strong>.`);return;}
if(action==='guard'){showFx("Guard!");F.e.guard=1;log.push("🛡️ Enemy takes a guarded stance.");return;}
const eFit=Math.max(0,+F.lvl||0);
let dmg=atkBaseFrom(eFit);
if(action==='heavy'){dmg=Math.floor(dmg*2.5);const dChance=enemyDodgeChance();if(Math.random()<dChance){log.push("🛡️ Enemy's heavy blow misses.");return;}showFx("Heavy!");log.push("💥 Enemy goes for a heavy blow!");}else{showFx("Attack!");}
if(F.p.guard>0)dmg=Math.floor(dmg*0.50);
if(F.p.exposed>0)dmg=Math.floor(dmg*1.30);
const fit=Math.max(0,+V.Fitness||0);
const pDodge=playerDodgeChance(fit);
if(action!=='heavy'&&Math.random()<pDodge){showFx("Evade!");log.push("🟦 You evade the enemy hit.");return;}
F.playerHP=Math.max(0,F.playerHP-dmg);
popNumber('#you-pop',`-${dmg}`);
flashHit('#you-card','#you-barbg');
log.push(`🔻 Enemy hits you: <strong>-${dmg} HP</strong>.`);
}
function spendSta(cost){if((+F.playerSta||0)<cost)return false;F.playerSta-=cost;return true;}
function doPlayerAttack(mode){
const fit=Math.max(0,+V.Fitness||0);
let log=[];
let cost=1;
if(mode==='heavy')cost=2;
if(mode==='heal')cost=2;
if(mode==='finish')cost=1;
if(mode==='guard')cost=0;
if(cost>0&&!spendSta(cost)){log.push("⚠️ Not enough stamina.");pushPopup("Fight",log);renderLog();updateHUD();return;}
if(mode==='guard')F.playerSta=clamp((+F.playerSta||0)+1,0,F.playerStaMax);
if(shouldPunch(mode))playPunchSfx();
startTurnTick(log);
if(endCheck()){updateHUD();return;}
if(mode==='guard'){showFx("Guard!");log.push("🛡️ You take a guarded stance. 50% less damage this turn.");F.p.guard=1;enemyActs(log);F.log=log;pushPopup("Fight",log);renderLog();updateHUD();endCheck();return;}
if(mode==='heal'){
if(F.healCD>0){log.push("⏳ Heal is on cooldown.");F.log=log;pushPopup("Fight",log);renderLog();updateHUD();return;}
const med=(V.Inventory&&V.Inventory.medkit)?V.Inventory.medkit:null;
const medQty=(med&&Number.isFinite(+med.qty))?Math.max(0,+med.qty):0;
if(medQty<=0){log.push("❌ You don't have a Medkit.");F.log=log;pushPopup("Fight",log);renderLog();updateHUD();return;}
V.Inventory.medkit.qty=Math.max(0,medQty-1);
const heal=Math.floor(F.playerMax*(0.28+Math.random()*0.04));
F.playerHP=Math.min(F.playerMax,F.playerHP+heal);
F.healCD=1;showFx("Heal!");log.push(`🩹 You heal: <strong>+${heal} HP</strong>.`);
enemyActs(log);F.log=log;pushPopup("Fight",log);renderLog();updateHUD();endCheck();return;
}
if(mode==='finish'){
if((F.enemyHP/F.enemyMax)>0.15){log.push("☠️ Finisher not available yet.");F.log=log;pushPopup("Fight",log);renderLog();updateHUD();return;}
showFx("Finisher!");log.push("☠️ You execute a brutal finisher!");F.enemyHP=0;popNumber('#foe-pop','KO');flashHit('#foe-card','#foe-barbg');F.log=log;pushPopup("Fight",log);renderLog();updateHUD();endCheck();return;
}
nudgeAttack('#you-card');
let dmg=atkBaseFrom(fit);
if(mode==='heavy'){
dmg=Math.floor(dmg*2.5);
showFx("Heavy!");log.push("💥 Heavy attack.");
const dChance=enemyDodgeChance();
if(Math.random()<dChance){showFx("Evaded!");log.push("🛡️ Enemy dodges the heavy blow.");F.log=log;pushPopup("Fight",log);renderLog();enemyActs(log);updateHUD();endCheck();return;}
if(F.p.adr>0){dmg=Math.floor(dmg*1.50);F.p.adr=0;log.push("⚡ Adrenaline boosts your strike.");}
if(F.e.exposed>0)dmg=Math.floor(dmg*1.30);
if(F.e.guard>0)dmg=Math.floor(dmg*0.50);
F.enemyHP=Math.max(0,F.enemyHP-dmg);
popNumber('#foe-pop',`-${dmg}`);flashHit('#foe-card','#foe-barbg');
F.p.adr=1;log.push(`🔺 Heavy hit lands: <strong>-${dmg} HP</strong>. Adrenaline builds.`);
} else {
showFx("Attack!");log.push("🥊 Standard attack.");
if(F.p.adr>0){dmg=Math.floor(dmg*1.50);F.p.adr=0;log.push("⚡ Adrenaline boosts your strike.");}
if(F.e.exposed>0)dmg=Math.floor(dmg*1.30);
if(F.e.guard>0)dmg=Math.floor(dmg*0.50);
const dChance=enemyDodgeChance();
if(Math.random()<dChance){const reduced=Math.floor(dmg*0.40);F.enemyHP=Math.max(0,F.enemyHP-reduced);popNumber('#foe-pop',`-${reduced}`);if(reduced>0)flashHit('#foe-card','#foe-barbg');log.push(`🛡️ Enemy partially dodges. Damage reduced to <strong>-${reduced} HP</strong>.`);}
else{F.enemyHP=Math.max(0,F.enemyHP-dmg);popNumber('#foe-pop',`-${dmg}`);flashHit('#foe-card','#foe-barbg');log.push(`🔺 You hit: <strong>-${dmg} HP</strong>.`);}
}
enemyActs(log);F.log=log;pushPopup("Fight",log);renderLog();updateHUD();endCheck();
}
function bind(sel,fn){const b=$q(sel);if(!b)return;const clone=b.cloneNode(true);b.parentNode.replaceChild(clone,b);clone.addEventListener('click',fn);}
bind('#btn-atk',()=>doPlayerAttack('atk'));
bind('#btn-heavy',()=>doPlayerAttack('heavy'));
bind('#btn-guard',()=>doPlayerAttack('guard'));
bind('#btn-heal',()=>doPlayerAttack('heal'));
bind('#btn-finish',()=>doPlayerAttack('finish'));
setBottom('');
pushPopup("Fight",["Choose an action."]);
updateHUD();
renderLog();
});
})();
<</script>><<set $Fight = {
type: "Man",
lvl: 65,
playerMax: $HealMax,
playerHP: $Heal,
enemyMax: 140,
enemyHP: 140,
playerBand: 0,
enemyBand: 1,
playerStaMax: 5,
playerSta: 5,
healCD: 0,
log: [],
p: {},
e: {},
enemyDodgeBias: 0.60
}>><<sound "music" "music.fight" true>><<passagebg>><<if $Time !== 3>><<sound "bg" "bg.city" true>><img src="assets/img/misc/oldtown/oldtown.webp"/><<else>><<sound "bg" "bg.cityNight" true>><img src="assets/img/misc/oldtown/oldtownnight.webp"/><</if>><</passagebg>><div id="fight-tip" style="display:none;"></div><div class="fight-ui" style="max-width:960px;margin:auto;"><div id="foe-card" class="foes card" style="display:flex;gap:12px;justify-content:space-between;align-items:center;padding:10px;border:1px solid #444;border-radius:10px;margin-bottom:10px;"><div style="width:100%;"><p style="margin:0;"><strong>Enemy:</strong> <span id="foe-type"></span> (Fitness <span id="foe-lvl"></span>) <span id="foe-states" class="states"></span></p><div class="hp-bar-bg" id="foe-barbg"><div id="foe-bar" class="hp-bar"></div><div class="pop-layer" id="foe-pop"></div></div><p style="margin:4px 0 0 0;">HP <span id="foe-hp"></span> / <span id="foe-max"></span> · 🩹 <span id="foe-band"></span></p></div></div><div id="you-card" class="you card" style="display:flex;gap:12px;justify-content:space-between;align-items:center;padding:10px;border:1px solid #444;border-radius:10px;margin-bottom:14px;"><div style="width:100%;"><p style="margin:0;"><strong>You</strong> (Fitness <span id="player-fit"></span>) <span id="you-states" class="states"></span></p><div class="hp-bar-bg" id="you-barbg"><div id="you-bar" class="hp-bar"></div><div class="pop-layer" id="you-pop"></div></div><div class="sta-row"><span class="sta-label">Stamina</span><div class="sta-bg"><div id="you-sta" class="sta-bar"></div></div><span id="you-sta-txt" class="sta-txt"></span></div><p style="margin:4px 0 0 0;">HP <span id="you-hp"></span> / <span id="you-max"></span> · 🩹 <span id="you-band"></span></p></div></div><div id="fight-actions" style="display:flex;gap:10px;flex-wrap:wrap;margin-bottom:10px;"><button id="btn-atk" type="button" data-tip="Standard attack. Deals solid damage based on your Fitness. Cost: 1 stamina.">🥊 Attack</button><button id="btn-heavy" type="button" data-tip="Heavy attack. Deals 2.5x damage based on Fitness, but costs 2 stamina and misses more often.">💥 Heavy</button><button id="btn-guard" type="button" data-tip="Guard. You take 50% less damage this turn. Cost: 0 stamina. Gain: +1 stamina.">🛡️ Guard</button><button id="btn-heal" type="button" data-tip="Heal using a Medkit. Cooldown: every other turn. Cost: 2 stamina. Requires: 1 Medkit.">🩹 Heal</button><button id="btn-finish" type="button" style="display:none;" data-tip="Finisher. Available when enemy HP is 15% or less. Ends the fight instantly. Cost: 1 stamina.">☠️ Finisher</button></div><div id="fight-popups"></div><div id="fight-stage"></div></div><div class="BottomUiBarCustom"><span style="display:contents;" id="fight-actionsbar"></span></div><style>#fight-tip{position:fixed;z-index:99999;display:none;max-width:280px;padding:8px 10px;border:1px solid rgba(255,255,255,.25);border-radius:10px;background:rgba(10,10,10,.92);backdrop-filter:blur(3px);color:#fff;font-size:.9rem;line-height:1.25;pointer-events:none;box-shadow:0 6px 18px rgba(0,0,0,.35);} .fight-ui p{line-height:1.3;} .fight-ui .card{background:rgba(255,255,255,0.03);} #fight-actions button{padding:8px 12px;border:1px solid #666;border-radius:8px;background:transparent;cursor:pointer;color:#fff;} #fight-actions button:hover{background:rgba(255,255,255,0.06);} #fight-actions button:disabled{opacity:.45;cursor:not-allowed;} .hp-bar-bg{position:relative;height:14px;background:#222;border-radius:7px;overflow:hidden;margin-top:6px;} .hp-bar{height:100%;width:100%;transition:width 250ms ease-in-out,background 250ms linear;} .pop-layer{position:absolute;inset:0;pointer-events:none;overflow:visible;} .dmg-pop{position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);font-weight:800;opacity:0;animation:popFloat 650ms ease-out forwards;text-shadow:0 1px 0 rgba(0,0,0,.55);} @keyframes popFloat{0%{opacity:0;transform:translate(-50%,-40%) scale(.9);}15%{opacity:1;}100%{opacity:0;transform:translate(-50%,-140%) scale(1.05);}} .hitFlash{animation:hitFlash 220ms ease-out;} @keyframes hitFlash{0%{filter:none;}40%{filter:brightness(1.35);}100%{filter:none;}} .shake{animation:shake 180ms ease-in-out;} @keyframes shake{0%{transform:translateX(0);}25%{transform:translateX(-3px);}50%{transform:translateX(3px);}75%{transform:translateX(-2px);}100%{transform:translateX(0);}} .attackNudge{animation:attackNudge 160ms ease-in-out;} @keyframes attackNudge{0%{transform:translateX(0);}50%{transform:translateX(3px);}100%{transform:translateX(0);}} .states{font-size:.85rem;opacity:.9;margin-left:8px;} .statePill{display:inline-block;padding:1px 6px;border:1px solid rgba(255,255,255,.25);border-radius:999px;margin-left:6px;font-size:.78rem;} .sta-row{display:flex;align-items:center;gap:8px;margin-top:8px;} .sta-label{font-size:.85rem;opacity:.9;} .sta-bg{height:10px;width:160px;border-radius:6px;background:#222;overflow:hidden;} .sta-bar{height:100%;width:100%;transition:width 200ms ease-in-out;background:#5090e2;} .sta-txt{font-size:.85rem;opacity:.9;min-width:34px;text-align:right;} .fxBadge{display:inline-block;margin-top:6px;font-weight:900;letter-spacing:.3px;opacity:0;animation:fxBadge 650ms ease-out forwards;} @keyframes fxBadge{0%{opacity:0;transform:translateY(2px) scale(.98);}20%{opacity:1;}100%{opacity:0;transform:translateY(-10px) scale(1.02);}}</style>
<<script>>
(function(){
$(document).on(':passagedisplay',function(ev){
if(!ev||!ev.passage||ev.passage.title!=='MayorStory17')return;
const V=State.variables;
const F=V.Fight||(V.Fight={type:"?",lvl:1,playerMax:100,enemyMax:100,playerHP:100,enemyHP:100,playerBand:0,enemyBand:1,playerStaMax:5,playerSta:5,healCD:0,log:[],p:{},e:{}});
const $q=(sel)=>document.querySelector(sel);
function playPunchSfx(){try{if(!window.setup||!setup.AudioMixer)return;setup.AudioMixer.playPlaylist("sfx","sfx.punch",false,{fadeInMs:0,fadeOutMs:0});}catch(e){}}
function shouldPunch(mode){return mode==='atk'||mode==='heavy'||mode==='finish';}
const tip=$q('#fight-tip');
function tipShow(text){if(!tip)return;tip.textContent=text;tip.style.display='block';}
function tipHide(){if(!tip)return;tip.style.display='none';}
function tipMove(e){if(!tip||tip.style.display==='none')return;const pad=14;let x=e.clientX+pad,y=e.clientY+pad;const r=tip.getBoundingClientRect();if(x+r.width>window.innerWidth-8)x=e.clientX-r.width-pad;if(y+r.height>window.innerHeight-8)y=e.clientY-r.height-pad;tip.style.left=x+'px';tip.style.top=y+'px';}
function bindTips(root){if(!root)return;root.addEventListener('mousemove',tipMove,{passive:true});root.addEventListener('mouseover',function(e){const el=e.target&&e.target.closest?e.target.closest('[data-tip]'):null;if(!el)return;const t=el.getAttribute('data-tip');if(t&&t.trim())tipShow(t.trim());});root.addEventListener('mouseout',function(e){const el=e.target&&e.target.closest?e.target.closest('[data-tip]'):null;if(!el)return;const to=e.relatedTarget&&e.relatedTarget.closest?e.relatedTarget.closest('[data-tip]'):null;if(to===el)return;tipHide();});}
bindTips($q('.fight-ui'));
function pct(v,max){return Math.max(0,Math.min(100,Math.floor((v/max)*100)));}
function clamp(n,min,max){return(n<min?min:(n>max?max:n));}
function barColor(percent){if(percent>70)return"#2ecc71";if(percent>35)return"#f1c40f";return"#e74c3c";}
function setActionsEnabled(enabled){['#btn-atk','#btn-heavy','#btn-guard','#btn-heal','#btn-finish'].forEach(sel=>{const b=$q(sel);if(b)b.disabled=!enabled;});}
function setBtnVisible(sel,visible){const b=$q(sel);if(!b)return;b.style.display=visible?'':'none';}
function popNumber(target,text){const layer=$q(target);if(!layer)return;const el=document.createElement('div');el.className='dmg-pop';el.textContent=text;layer.appendChild(el);setTimeout(()=>{try{el.remove();}catch(e){}},700);}
function flashHit(cardSel,barBgSel){const c=$q(cardSel),b=$q(barBgSel);if(c){c.classList.remove('shake');c.classList.add('shake');setTimeout(()=>c.classList.remove('shake'),220);}if(b){b.classList.remove('hitFlash');b.classList.add('hitFlash');setTimeout(()=>b.classList.remove('hitFlash'),260);}}
function nudgeAttack(cardSel){const c=$q(cardSel);if(!c)return;c.classList.remove('attackNudge');c.classList.add('attackNudge');setTimeout(()=>c.classList.remove('attackNudge'),220);}
function showFx(text){const box=$q('#fight-stage');if(!box)return;const el=document.createElement('div');el.className='fxBadge';el.textContent=text;box.prepend(el);setTimeout(()=>{try{el.remove();}catch(e){}},700);}
function renderLog(){const box=$q('#fight-stage');if(!box)return;box.innerHTML='';}
function setBottom(wiki){const slot=$q('#fight-actionsbar');if(!slot)return;try{slot.innerHTML='';slot.appendChild(Wikifier.wikifyEval(String(wiki||'')));}catch(e){}}
function pushPopup(title,lines){const box=$q('#fight-popups');if(!box)return;try{box.innerHTML='';const t=String(title||'Info').replace(/"/g,'"');const arr=Array.isArray(lines)?lines:((lines!=null)?[String(lines)]:[]);const html=arr.filter(Boolean).map(s=>String(s)).join('<br>');box.appendChild(Wikifier.wikifyEval('<<InformationUiPopUp "'+t+'">>'+html+'<</InformationUiPopUp>>'));}catch(e){}}
function victoryScreen(){
const box=$q('#fight-stage');if(!box)return;
setActionsEnabled(false);box.innerHTML='';
pushPopup("Victory",["🏆 Victory! The enemy is defeated."]);
setBottom('<<BottomButton "Move">><<link "➡️ Continue">><<goto "MayorStory18">><</link>><</BottomButton>>');
}
function defeatScreen(){
const box=$q('#fight-stage');if(!box)return;
setActionsEnabled(false);box.innerHTML='';
pushPopup("Defeat",["💥 You are knocked out."]);
setBottom('<<BottomButton "Move">><<link "Continue">><<goto "End.Fight">><</link>><</BottomButton>>');
}
function applyDotsAndTick(sideKey,log){
const S=(sideKey==='p')?F.p:F.e;
if(S.bleed&&S.bleed>0){const dmg=Math.max(1,+S.bleedDmg||2);if(sideKey==='p'){F.playerHP=Math.max(0,F.playerHP-dmg);popNumber('#you-pop',`-${dmg}`);flashHit('#you-card','#you-barbg');log.push(`🩸 Bleeding tick on you: <strong>-${dmg} HP</strong>.`);}else{F.enemyHP=Math.max(0,F.enemyHP-dmg);popNumber('#foe-pop',`-${dmg}`);flashHit('#foe-card','#foe-barbg');log.push(`🩸 Bleeding tick on enemy: <strong>-${dmg} HP</strong>.`);}S.bleed-=1;}
if(S.guard&&S.guard>0)S.guard-=1;
if(S.exposed&&S.exposed>0)S.exposed-=1;
if(S.adr&&S.adr>0)S.adr-=1;
if(S.stun&&S.stun>0)S.stun-=1;
if(sideKey==='p'){V.Heal=F.playerHP;}
}
function pill(label,tipText){return`<span class="statePill" data-tip="${String(tipText).replace(/"/g,'"')}">${label}</span>`;}
function statePills(S){
let out=[];
if(S.stun>0)out.push(pill(`Stunned ${S.stun}`,"Stunned: skips the next turn."));
if(S.bleed>0)out.push(pill(`Bleeding ${S.bleed}`,"Bleeding: takes damage at the start of each turn."));
if(S.guard>0)out.push(pill("Guarded","Guarded: takes 50% less damage this turn."));
if(S.exposed>0)out.push(pill("Exposed","Exposed: takes 30% more damage."));
if(S.adr>0)out.push(pill("Adrenaline","Adrenaline: your next hit deals 50% more damage."));
return out.join('');
}
function updateHUD(){
const foeType=$q('#foe-type'),foeLvl=$q('#foe-lvl'),foeHP=$q('#foe-hp'),foeMax=$q('#foe-max'),foeBand=$q('#foe-band'),foeBar=$q('#foe-bar'),foeStates=$q('#foe-states');
const youFit=$q('#player-fit'),youHP=$q('#you-hp'),youMax=$q('#you-max'),youBand=$q('#you-band'),youBar=$q('#you-bar'),youStates=$q('#you-states');
const youSta=$q('#you-sta'),youStaTxt=$q('#you-sta-txt');
if(!foeType||!foeLvl||!foeHP||!foeMax||!foeBand||!foeBar||!youFit||!youHP||!youMax||!youBand||!youBar)return;
foeType.textContent=F.type;foeLvl.textContent=F.lvl;foeHP.textContent=F.enemyHP;foeMax.textContent=F.enemyMax;foeBand.textContent=F.enemyBand;
const foePct=pct(F.enemyHP,F.enemyMax);foeBar.style.width=foePct+'%';foeBar.style.background=barColor(foePct);
if(foeStates)foeStates.innerHTML=statePills(F.e);
const fit=Math.max(0,+V.Fitness||0);
youFit.textContent=fit;youHP.textContent=F.playerHP;youMax.textContent=F.playerMax;
const medQty=(V.Inventory&&V.Inventory.medkit&&Number.isFinite(+V.Inventory.medkit.qty))?Math.max(0,+V.Inventory.medkit.qty):0;
youBand.textContent=medQty;
const youPct=pct(F.playerHP,F.playerMax);youBar.style.width=youPct+'%';youBar.style.background=barColor(youPct);
if(youStates)youStates.innerHTML=statePills(F.p);
const staPct=pct(F.playerSta,F.playerStaMax);
if(youSta)youSta.style.width=staPct+'%';
if(youStaTxt)youStaTxt.textContent=`${F.playerSta}/${F.playerStaMax}`;
setBtnVisible('#btn-finish',(F.enemyHP>0&&(F.enemyHP/F.enemyMax)<=0.15));
const healBtn=$q('#btn-heal');
if(healBtn)healBtn.textContent=(F.healCD>0)?'🩹 Heal (CD)':'🩹 Heal';
}
function endCheck(){if(F.playerHP<=0){defeatScreen();return true;}if(F.enemyHP<=0){victoryScreen();return true;}return false;}
function atkBaseFrom(fit){return Math.floor(Math.random()*6)+6+Math.floor(fit/4);}
function enemyDodgeChance(){
let base=clamp(0.25+(Math.max(1,+F.lvl||1)/400),0.25,0.75);
base=clamp(base+((+F.enemyDodgeBias||0.5)-0.5)*0.25,0.15,0.85);
if(F.e.exposed>0)base=base*0.50;
return clamp(base,0.10,0.90);
}
function playerDodgeChance(fit){return clamp(0.10+(fit/200),0.10,0.60);}
function regenCooldownOnly(){if(F.healCD>0)F.healCD-=1;}
function startTurnTick(log){applyDotsAndTick('p',log);applyDotsAndTick('e',log);regenCooldownOnly();}
function enemyActs(log){
if(F.e.stun>0){log.push("😵 Enemy is stunned and skips the turn.");return;}
let action='atk';
const hpPct=F.enemyHP/F.enemyMax;
const roll=Math.random();
if(hpPct<=0.25&&F.enemyBand>0)action='heal';
else if(roll<0.20)action='guard';
else if(roll<0.40)action='heavy';
else action='atk';
if(action==='heal'){const h=Math.floor(F.enemyMax*(0.28+Math.random()*0.04));F.enemyHP=Math.min(F.enemyMax,F.enemyHP+h);F.enemyBand=Math.max(0,(+F.enemyBand||0)-1);showFx("Heal!");log.push(`🩹 Enemy heals: <strong>+${h} HP</strong>.`);return;}
if(action==='guard'){showFx("Guard!");F.e.guard=1;log.push("🛡️ Enemy takes a guarded stance.");return;}
const eFit=Math.max(0,+F.lvl||0);
let dmg=atkBaseFrom(eFit);
if(action==='heavy'){dmg=Math.floor(dmg*2.5);const dChance=enemyDodgeChance();if(Math.random()<dChance){log.push("🛡️ Enemy's heavy blow misses.");return;}showFx("Heavy!");log.push("💥 Enemy goes for a heavy blow!");}else{showFx("Attack!");}
if(F.p.guard>0)dmg=Math.floor(dmg*0.50);
if(F.p.exposed>0)dmg=Math.floor(dmg*1.30);
const fit=Math.max(0,+V.Fitness||0);
const pDodge=playerDodgeChance(fit);
if(action!=='heavy'&&Math.random()<pDodge){showFx("Evade!");log.push("🟦 You evade the enemy hit.");return;}
F.playerHP=Math.max(0,F.playerHP-dmg);
popNumber('#you-pop',`-${dmg}`);
flashHit('#you-card','#you-barbg');
log.push(`🔻 Enemy hits you: <strong>-${dmg} HP</strong>.`);
}
function spendSta(cost){if((+F.playerSta||0)<cost)return false;F.playerSta-=cost;return true;}
function doPlayerAttack(mode){
const fit=Math.max(0,+V.Fitness||0);
let log=[];
let cost=1;
if(mode==='heavy')cost=2;
if(mode==='heal')cost=2;
if(mode==='finish')cost=1;
if(mode==='guard')cost=0;
if(cost>0&&!spendSta(cost)){log.push("⚠️ Not enough stamina.");pushPopup("Fight",log);renderLog();updateHUD();return;}
if(mode==='guard')F.playerSta=clamp((+F.playerSta||0)+1,0,F.playerStaMax);
if(shouldPunch(mode))playPunchSfx();
startTurnTick(log);
if(endCheck()){updateHUD();return;}
if(mode==='guard'){showFx("Guard!");log.push("🛡️ You take a guarded stance. 50% less damage this turn.");F.p.guard=1;enemyActs(log);F.log=log;pushPopup("Fight",log);renderLog();updateHUD();endCheck();return;}
if(mode==='heal'){
if(F.healCD>0){log.push("⏳ Heal is on cooldown.");F.log=log;pushPopup("Fight",log);renderLog();updateHUD();return;}
const med=(V.Inventory&&V.Inventory.medkit)?V.Inventory.medkit:null;
const medQty=(med&&Number.isFinite(+med.qty))?Math.max(0,+med.qty):0;
if(medQty<=0){log.push("❌ You don't have a Medkit.");F.log=log;pushPopup("Fight",log);renderLog();updateHUD();return;}
V.Inventory.medkit.qty=Math.max(0,medQty-1);
const heal=Math.floor(F.playerMax*(0.28+Math.random()*0.04));
F.playerHP=Math.min(F.playerMax,F.playerHP+heal);
F.healCD=1;showFx("Heal!");log.push(`🩹 You heal: <strong>+${heal} HP</strong>.`);
enemyActs(log);F.log=log;pushPopup("Fight",log);renderLog();updateHUD();endCheck();return;
}
if(mode==='finish'){
if((F.enemyHP/F.enemyMax)>0.15){log.push("☠️ Finisher not available yet.");F.log=log;pushPopup("Fight",log);renderLog();updateHUD();return;}
showFx("Finisher!");log.push("☠️ You execute a brutal finisher!");F.enemyHP=0;popNumber('#foe-pop','KO');flashHit('#foe-card','#foe-barbg');F.log=log;pushPopup("Fight",log);renderLog();updateHUD();endCheck();return;
}
nudgeAttack('#you-card');
let dmg=atkBaseFrom(fit);
if(mode==='heavy'){
dmg=Math.floor(dmg*2.5);
showFx("Heavy!");log.push("💥 Heavy attack.");
const dChance=enemyDodgeChance();
if(Math.random()<dChance){showFx("Evaded!");log.push("🛡️ Enemy dodges the heavy blow.");F.log=log;pushPopup("Fight",log);renderLog();enemyActs(log);updateHUD();endCheck();return;}
if(F.p.adr>0){dmg=Math.floor(dmg*1.50);F.p.adr=0;log.push("⚡ Adrenaline boosts your strike.");}
if(F.e.exposed>0)dmg=Math.floor(dmg*1.30);
if(F.e.guard>0)dmg=Math.floor(dmg*0.50);
F.enemyHP=Math.max(0,F.enemyHP-dmg);
popNumber('#foe-pop',`-${dmg}`);flashHit('#foe-card','#foe-barbg');
F.p.adr=1;log.push(`🔺 Heavy hit lands: <strong>-${dmg} HP</strong>. Adrenaline builds.`);
} else {
showFx("Attack!");log.push("🥊 Standard attack.");
if(F.p.adr>0){dmg=Math.floor(dmg*1.50);F.p.adr=0;log.push("⚡ Adrenaline boosts your strike.");}
if(F.e.exposed>0)dmg=Math.floor(dmg*1.30);
if(F.e.guard>0)dmg=Math.floor(dmg*0.50);
const dChance=enemyDodgeChance();
if(Math.random()<dChance){const reduced=Math.floor(dmg*0.40);F.enemyHP=Math.max(0,F.enemyHP-reduced);popNumber('#foe-pop',`-${reduced}`);if(reduced>0)flashHit('#foe-card','#foe-barbg');log.push(`🛡️ Enemy partially dodges. Damage reduced to <strong>-${reduced} HP</strong>.`);}
else{F.enemyHP=Math.max(0,F.enemyHP-dmg);popNumber('#foe-pop',`-${dmg}`);flashHit('#foe-card','#foe-barbg');log.push(`🔺 You hit: <strong>-${dmg} HP</strong>.`);}
}
enemyActs(log);F.log=log;pushPopup("Fight",log);renderLog();updateHUD();endCheck();
}
function bind(sel,fn){const b=$q(sel);if(!b)return;const clone=b.cloneNode(true);b.parentNode.replaceChild(clone,b);clone.addEventListener('click',fn);}
bind('#btn-atk',()=>doPlayerAttack('atk'));
bind('#btn-heavy',()=>doPlayerAttack('heavy'));
bind('#btn-guard',()=>doPlayerAttack('guard'));
bind('#btn-heal',()=>doPlayerAttack('heal'));
bind('#btn-finish',()=>doPlayerAttack('finish'));
setBottom('');
pushPopup("Fight",["Choose an action."]);
updateHUD();
renderLog();
});
})();
<</script>><<sound "music" "music.music" true>><<passagebg>><<if $Time !== 3>><<sound "bg" "bg.city" true>><img src="assets/img/misc/oldtown/oldtown.webp"/><<else>><<sound "bg" "bg.cityNight" true>><img src="assets/img/misc/oldtown/oldtownnight.webp"/><</if>><</passagebg>><<InformationUiPopUp>>I catch my breath, hands on my knees, looking at the two men on the ground. No doubt about who sent them. Hargrove. And unlike every other time, this was direct.
<</InformationUiPopUp>>
<<TalkMC "I'm done with these guys, they're putting way too much pressure on me... I got lucky getting out of a two on one...">>
<<InformationUiPopUp>>I leave the alley quickly, moving through the old district streets at a steady pace despite everything that just happened. I think as I walk. The woman, the tail, the job for W., and now this ambush. Hargrove isn't stopping, they keep coming without giving me room to breathe. They're not going to stop, and the next attempt will probably be the last.
<</InformationUiPopUp>>
<<TalkMC "There's only one way to end this cleanly. The mayor. The land. I need to finish this now.">>
<div class="BottomUiBarCustom">
<<BottomButton "Move">><<link "➡️ Go">><<goto "Oldtown">><<set $MayorStoryInfo9 = true>><</link>><</BottomButton>>
</div><<sound "music" "music.music" true>><<sound "bg" "bg.empty" true>><<passagebg>><img src="assets/img/misc/city/cityhall/mayoroffice.webp"/><</passagebg>><<set _npc = $NPCMayor>><<TalkNPC _npc "Great, you're here, go ahead, have a seat.">>
<<TalkMC "Your message said something had moved forward?">>
<<TalkNPC _npc "Hargrove has lost the construction rights on the financial district site. Officially, the suspension became a revocation after the geological file was reviewed, so their permits are cancelled.">>
<<TalkMC "Is that final?">>
<<TalkNPC _npc "Final. Their lawyers will contest it, that's inevitable, but on the substance they have nothing.">>
<<InformationUiPopUp>>She sets her hands on the desk.
<</InformationUiPopUp>>
<<TalkNPC _npc "Now here's the problem. The site is free, but the construction was already well underway. That represents a very concrete opportunity, and several parties have already positioned themselves to take it over. Developers, investment funds, groups with a lot more structure than you.">>
<<TalkMC "So?">>
<<TalkNPC _npc "So I'm stalling. I'm slowing the administrative process down as much as I legally can to give you time to get into position. But I won't be able to do that indefinitely.">>
<<TalkMC "What do I need to do?">>
<<TalkNPC _npc "Honestly, I was just waiting for your confirmation. On my end, the documents are ready. All it takes is a signature, and the construction rights are attributed to you with the priority I was able to secure. And you take the project over from where Hargrove left off.">>
<<TalkMC "I'm guessing it still won't be free. How much are we talking?">>
<<TalkNPC _npc "That's where it gets complicated for you. With the construction already underway, the land value has been reassessed, so it won't cost as much as if the site were empty. But now that the geological file has come out publicly, the revised foundation costs have been factored into the estimates. Based on current figures, we're talking over thirty million dollars.">>
<<TalkMC "I don't have that.">>
<<TalkNPC _npc "I suspected as much. But the city can provide partial financial assistance as part of an urban development project. And for the rest, you can take out a loan. Banks finance this type of real estate acquisition, especially with an official construction right in hand.">>
<<InformationUiPopUp>>I stay quiet for a moment. Thirty million. A loan of that scale is a decision that commits years. But the land, the building already half constructed, the position it gives in the financial district, this is exactly what I had in mind from the start.
<</InformationUiPopUp>>
<<TalkMC "Okay. I accept.">>
<<TalkNPC _npc "Good.">>
<<InformationUiPopUp>>She opens a drawer and sets a document on the desk in front of me. Several pages, already prepared, with signature markers throughout.
<</InformationUiPopUp>>
<<TalkNPC _npc "This document certifies your construction rights on the parcel, with acquisition priority granted by the city. Once signed, it's official. Nobody else can position themselves on it.">>
<<InformationUiPopUp>>I go through the pages quickly, then sign. She countersigns, stamps it, and hands me a copy.
<</InformationUiPopUp>>
<<TalkNPC _npc "Go see your bank. With this document, you have something concrete to present.">>
<<TalkMC "I'll be in touch once it's done.">>
<<InformationUiPopUp>>I walk out of the office with the document under my arm. In the corridor, I glance down at the paper. The land is mine, in black and white, with my name on it. All that's left is convincing the bank.
<</InformationUiPopUp>>
<div class="BottomUiBarCustom">
<<BottomButton "Move">><<link "➡️ Go">><<goto "CHMayorOffice">><<set $MayorStoryInfo11 = true>><<set $Inventory.acquisitiondocument = {id:"acquisitiondocument", name:"Acquisition Document", price:0, img:"assets/img/items/story/acquisitiondocument.webp", unique:true, inventory:true, bought:true, desc:"A useful item for the story.", qty:1}>><</link>><</BottomButton>>
</div><<sound "music" "music.music" true>><<sound "bg" "bg.empty" true>><<passagebg>><img src="assets/img/misc/financialquarter/bank.webp"/><</passagebg>><<InformationUiPopUp>>I walk up to the counter, an employee looks up at me.
<</InformationUiPopUp>>
<<TalkRandom "Receptionist" "assets/img/character/npc/g1.jpg" "Hello, can I help you?">>
<<TalkMC "Hello. I'd like to make an appointment with a banker for a loan application, it's for a real estate construction project.">>
<<TalkRandom "Receptionist" "assets/img/character/npc/g1.jpg" "Of course, let me check availability. One moment please.">>
<<InformationUiPopUp>>She looks at her screen, types a few keys, then looks back up.
<</InformationUiPopUp>>
<<TalkRandom "Receptionist" "assets/img/character/npc/g1.jpg" "I'll see if someone is available to see you now. Can you wait in the waiting area?">>
<<TalkMC "Of course.">>
<<revealtext "wait">><<InformationUiPopUp>>I sit down in the waiting area. A few minutes pass. Then a woman comes out of a corridor and walks toward me.
<</InformationUiPopUp>>
<<TalkRandom "Banker" "assets/img/character/npc/g7.jpg" "Hello, I'm Lyra, a financing advisor. I was told you'd like to discuss a loan for a real estate project?">>
<<TalkMC "That's right.">>
<<TalkRandom "Banker" "assets/img/character/npc/g7.jpg" "Follow me, we'll talk about it in my office.">><</revealtext>>
<<revealtext "enter">><<passagebg>><img src="assets/img/story/mayorstory/bankoffice.webp"/><</passagebg>><<InformationUiPopUp>>Her office is large, with an entire wall lined with books. We each sit on either side of the desk. She opens her computer and picks up a pen.
<</InformationUiPopUp>>
<<TalkRandom "Banker" "assets/img/character/npc/g7.jpg" "So, what kind of project?">>
<<TalkMC "A takeover of construction rights on a building site in the financial district. The city has granted me acquisition priority.">>
<<InformationUiPopUp>>I set the document on the desk. She picks it up and starts reading it carefully.
<</InformationUiPopUp>>
<<TalkRandom "Banker" "assets/img/character/npc/g7.jpg" "And the loan amount you're looking for?">>
<<TalkMC "Around thirty million dollars.">>
<<InformationUiPopUp>>She pauses in her reading, then continues without saying anything. Once she sets the document down, she types something into her computer, takes a few seconds, then looks at me.
<</InformationUiPopUp>>
<<TalkRandom "Banker" "assets/img/character/npc/g7.jpg" "I'll be direct with you. The city document is in order, I'm not disputing that. But before meeting with you, I looked into your financial profile. And honestly, what I have in front of me doesn't allow me to approve a loan of this scale.">>
<<TalkMC "What exactly is the problem?">>
<<TalkRandom "Banker" "assets/img/character/npc/g7.jpg" "Your repayment capacity in the event of difficulties. A construction project of this size carries significant risks. Delays, cost overruns, market fluctuations. If the project were to go wrong, you don't have sufficient guarantees to cover a thirty million dollar loan.">>
<<TalkMC "The city is providing partial financial assistance, and the building is already half constructed, so the risk is much lower than for a project starting from scratch.">>
<<TalkRandom "Banker" "assets/img/character/npc/g7.jpg" "I understand your point, but it's not enough to meet our evaluation criteria. The project remains risky on paper.">>
<<TalkMC "The construction rights themselves represent a concrete guarantee, the land value alone covers a significant portion of the loan.">>
<<TalkRandom "Banker" "assets/img/character/npc/g7.jpg" "The land value is indeed taken into account, but it's not enough to offset the absence of stable income and sufficient personal guarantees. I'm sorry, my answer remains no.">>
<<InformationUiPopUp>>I can see she won't budge. Whatever argument I make, the answer will be the same. I have only one option left.
<</InformationUiPopUp>><</revealtext>>
<<revealtext "power">><<InformationUiPopUp "Psychic Power" #7aa2ff>>You decide to use your power on the Banker.
<em>-1 Psychic Power</em><</InformationUiPopUp>>
<<TalkMC "Listen to me.">>
<<TalkMC "You're going to approve this loan. You believe in this project, you believe in my ability to repay with interest. You know this is the right file and that you won't regret this decision. And to apologize for turning me down at the start, you're going to suck me off while we sign the documents.">>
<<TalkRandom "Banker" "assets/img/character/npc/g7.jpg" "...">>
<<InformationUiPopUp>>Her expression shifts slowly. She sets down her pen and turns toward her computer, then opens a new document.
<</InformationUiPopUp>>
<<TalkRandom "Banker" "assets/img/character/npc/g7.jpg" "Thinking about it more, the file is solid. The municipal priority is something that often gets underestimated. I think we can find a loan structure that works.">>
<<TalkMC "I'm glad we're on the same page.">>
<<TalkRandom "Banker" "assets/img/character/npc/g7.jpg" "I'll get the documents ready. And... I wanted to apologize for my initial refusal. It was clearly a significant professional error, a misreading of the file.">>
<<InformationUiPopUp>>She comes around the desk, I stand up and she kneels in front of me. She pulls out my cock and sucks me off while her computer prints the loan documents.
<</InformationUiPopUp>>
<video src="assets/img/story/mayorstory/banker/01.mp4"/>
<<TalkRandom "Banker" "assets/img/character/npc/g7.jpg" "<em>Mmh... glrk... mmh...</em>">>
<<InformationUiPopUp>>While she sucks me off, I twist the top half of my body to the side to sign the documents.
<</InformationUiPopUp>>
<video src="assets/img/story/mayorstory/banker/02.mp4"/>
<<TalkRandom "Banker" "assets/img/character/npc/g7.jpg" "<em>Mmh...</em>">>
<<InformationUiPopUp>>I sign the last page. She finishes a few seconds later, stands up, straightens herself out, and stamps the documents with the same professionalism as at the start of the meeting. She hands me the complete file.
<</InformationUiPopUp>>
<<TalkRandom "Banker" "assets/img/character/npc/g7.jpg" "There you go. The transfer will be processed within forty-eight business hours. Good luck with your project.">>
<<TalkMC "Thank you for everything.">>
<<InformationUiPopUp>>I walk out of the bank with the file under my arm. Now that the loan is approved, the land is officially mine. All that's left is to build.
<</InformationUiPopUp>><</revealtext>>
<div class="BottomUiBarCustom">
<<BottomButton "Story">><<revealbtn "wait" "⏳ Wait" "" "wait" "enter" true>><</revealbtn>><<revealbtn "enter" "➡️ Enter" "" "enter" "power" false>><</revealbtn>><<revealbtn "power" "🧠 Use power" "moveBtn" "power" "" false>><<UsePsychicPower>><</revealbtn>><</BottomButton>>
<<BottomButton "Story" "moveBtn">><<link "🚪 Exit">><<goto "Bank">><<set $MayorStoryInfo12 = true>><<set $PsychicPower -= 1>><</link>><</BottomButton>>
</div><<sound "music" "music.music" true>><<passagebg>><img src="assets/img/misc/MCPC/internet/email/reading.gif"/><</passagebg>><<InformationUiPopUp "Email">><strong>Subject:</strong> Loan Approval Confirmation - Construction Project Financing
<strong>From:</strong> Lyra - First City Bank
<strong>To:</strong> <<print $MCPlayer.firstname>> <<print $MCPlayer.lastname>>
Dear <<print $MCPlayer.firstname>> <<print $MCPlayer.lastname>>,
We are pleased to confirm that your loan application has been reviewed and officially approved by First City Bank.
<strong>Loan Summary:</strong>
- <strong>Total Amount:</strong> $30,000,000
- <strong>Purpose:</strong> Construction project financing - Financial District
- <strong>Repayment Start:</strong> Upon completion of construction
- <strong>Repayment Schedule:</strong> $10,000 every 7 days until full repayment
The funds have been transferred to your bank account as of the date of this confirmation.
Please note that repayment will begin automatically once the construction project is completed and certified. You will receive a separate notification at that time confirming the start of your repayment schedule.
All signed documents are archived in our offices. If you have any questions regarding the terms of your loan or the repayment process, please do not hesitate to contact us directly.
We wish you every success in your project.
Sincerely,
Lyra
Financing Advisor
First City Bank
<</InformationUiPopUp>>
<<revealtext "talk">><<TalkMC "Perfect, now that the loan is confirmed, construction can start back up. But it's absolutely not over for me...">>
<<InformationUiPopUp>>I look at the email one last time. Thirty million, ten thousand dollars every seven days once construction is finished. That's absolutely not manageable for me right now.
<</InformationUiPopUp>>
<<TalkMC "I could re-corrupt the banker to cancel the loan... No, bad idea, that's just going to draw attention for nothing.">>
<<InformationUiPopUp>>I'm going to have to think about different ways to make a lot more money. I already have my camgirl site helping, but it's absolutely not enough.
<</InformationUiPopUp>>
<<TalkMC "Anyway, I'll have time to think about that later. Before any of that, I need to go see the mayor to confirm the start of construction. Without her official green light, the site can't resume.">><</revealtext>>
<div class="BottomUiBarCustom">
<<BottomButton "Story">><<revealbtn "talk" "➡️ Continue" "moveBtn" "talk" "" true>><</revealbtn>><</BottomButton>>
<<BottomButton "Story" "moveBtn">><<link "➡️ Perfect">><<set $MayorStoryInfo13 = true>><<goto $MailReturnTo>><<set $MailReturnTo = "">><</link>><</BottomButton>>
</div><<sound "music" "music.music" true>><<passagebg>><<if $Time !== 3>><<sound "bg" "bg.city" true>><img src="assets/img/misc/financialquarter/building/buildongoing.webp"/><<else>><<sound "bg" "bg.cityNight" true>><img src="assets/img/misc/financialquarter/building/buildongoingnight.webp"/><</if>><</passagebg>><<InformationUiPopUp>>I arrive at the construction site, making my way onto the lot. The foundations are already in place, the machinery sitting idle for several weeks now. A man in a yellow hard hat turns around as he hears me approaching.
<</InformationUiPopUp>>
<<TalkRandom "Site Manager" "assets/img/character/npc/b4.jpg" "This is a construction zone, you can't just walk in like that.">>
<<TalkMC "I'm the new project owner. <<print $MCPlayer.firstname>> <<print $MCPlayer.lastname>>.">>
<<InformationUiPopUp>>He looks at me for a moment, then takes off his hard hat and holds out his hand.
<</InformationUiPopUp>>
<<TalkRandom "Site Manager" "assets/img/character/npc/b4.jpg" "Marcus Webb, site manager. I'd heard there was something new on the file, but we were waiting for official confirmation.">>
<<TalkMC "Here it is.">>
<<InformationUiPopUp>>I hand him the documents signed by the city. He goes through them quickly, stopping on the key pages, then hands them back to me.
<</InformationUiPopUp>>
<<TalkRandom "Site Manager" "assets/img/character/npc/b4.jpg" "Everything's in order. We've been waiting on the restart for several weeks now, the crews have been dispersed but most of them are still available, I can call them back.">>
<<TalkMC "Do it. I want work to resume today if possible.">>
<<TalkRandom "Site Manager" "assets/img/character/npc/b4.jpg" "That should be doable, I'll start making calls right now. We can pick up right where we left off. The foundations were reinforced following the geological report, the bulk of what's left is the structure and the finishes.">>
<<TalkMC "How long to finish?">>
<<TalkRandom "Site Manager" "assets/img/character/npc/b4.jpg" "If everything goes smoothly, sixty days. It'll depend on material deliveries and weather conditions, but we'll move as fast as we can.">>
<<TalkMC "Good. Keep me posted when it's done.">>
<<TalkRandom "Site Manager" "assets/img/character/npc/b4.jpg" "Of course, don't worry about that.">>
<<InformationUiPopUp>>He puts his hard hat back on and heads toward the structures, already on the phone. I stay for a moment looking at the site. In sixty days, there will be a building there. My building.
<</InformationUiPopUp>>
<div class="BottomUiBarCustom">
<<BottomButton "Story">><<link "➡️ Here we go">><<set $MayorStoryFinish = true>><<goto "Building">><</link>><</BottomButton>>
</div><<sound "music" "music.music" true>><<passagebg>><<if $Time !== 3>><<sound "bg" "bg.city" true>><img src="assets/img/misc/financialquarter/building/buildongoing.webp"/><<else>><<sound "bg" "bg.cityNight" true>><img src="assets/img/misc/financialquarter/building/buildongoingnight.webp"/><</if>><</passagebg>>
<<InformationUiPopUp "⚠️ Important ⚠️" "#e65763">>The rest of the chapter is still in development and is therefore not available.
<</InformationUiPopUp>>
<<imgcorruption city>>
<div class="BottomUiBarCustom"><<if $MayorStoryInfo14 == true and $MayorStoryFinish == false>><br><<BottomButton "Story">><<link "💬 Talk about the Building">><<goto "MayorStory22">><</link>><</BottomButton>><</if>>
<<BottomButton "Move">>[[🏬 Financial district|FinancialQuarter]]<</BottomButton>>
</div><<set $ShowTopUiBar = false>><<set $ShowBottomUiBar = false>><style>
#gal-app{position:fixed;inset:0;z-index:10;background:#080808;color:#edf0f7;display:flex;flex-direction:column;font-family:inherit;overflow:hidden;}
#gal-hdr{display:flex;align-items:center;gap:10px;padding:10px 16px;border-bottom:1px solid rgba(255,255,255,.08);background:rgba(255,255,255,.02);flex-shrink:0;flex-wrap:wrap;}
#gal-title{font-size:calc(16px + var(--font-boost,0px));font-weight:900;color:#fff;white-space:nowrap;}
#gal-cats-bar{flex:1;overflow-x:auto;min-width:0;}
#gal-cats{display:flex;gap:5px;padding:2px 0;}
.gal-cat{all:unset;padding:5px 12px;border-radius:8px;font-size:calc(14px + var(--font-boost,0px));font-weight:700;cursor:pointer;white-space:nowrap;border:1px solid rgba(255,255,255,.10);background:rgba(255,255,255,.04);color:rgba(255,255,255,.55);transition:all .15s;}
.gal-cat:hover{background:rgba(255,255,255,.08);color:#fff;}
.gal-cat.on{background:rgba(230,87,99,.14);border-color:rgba(230,87,99,.40);color:rgba(230,87,99,.95);}
#gal-back{all:unset;padding:6px 13px;border-radius:8px;border:1px solid rgba(255,255,255,.13);background:rgba(255,255,255,.04);color:rgba(255,255,255,.60);font-size:calc(14px + var(--font-boost,0px));font-weight:700;cursor:pointer;white-space:nowrap;transition:all .15s;flex-shrink:0;}
#gal-back:hover{background:rgba(255,255,255,.10);color:#fff;}
#gal-reset{all:unset;padding:6px 13px;border-radius:8px;border:1px solid rgba(230,87,99,.25);background:rgba(230,87,99,.06);color:rgba(230,87,99,.75);font-size:calc(14px + var(--font-boost,0px));font-weight:700;cursor:pointer;white-space:nowrap;transition:all .15s;flex-shrink:0;}
#gal-reset:hover{background:rgba(230,87,99,.15);color:rgba(230,87,99,1);}
#gal-reset.gal-confirm{background:rgba(230,87,99,.85)!important;color:#fff!important;border-color:rgba(230,87,99,1)!important;}
#gal-sub-bar{display:none;padding:6px 16px 8px;border-bottom:1px solid rgba(255,255,255,.06);flex-shrink:0;overflow-x:auto;}
#gal-sub-bar.active{display:block;}
#gal-subs{display:flex;gap:5px;}
.gal-sub{all:unset;padding:4px 11px;border-radius:7px;font-size:calc(13px + var(--font-boost,0px));font-weight:700;cursor:pointer;white-space:nowrap;border:1px solid rgba(255,255,255,.08);background:rgba(255,255,255,.03);color:rgba(255,255,255,.45);transition:all .15s;}
.gal-sub:hover{background:rgba(255,255,255,.07);color:#fff;}
.gal-sub.on{background:rgba(230,87,99,.11);border-color:rgba(230,87,99,.32);color:rgba(230,87,99,.90);}
#gal-body{display:flex;flex:1;overflow:hidden;min-height:0;}
#gal-browser{width:340px;flex-shrink:0;border-right:1px solid rgba(255,255,255,.08);background:rgba(255,255,255,.01);display:flex;flex-direction:column;overflow:hidden;}
.gal-panel-hdr{display:flex;align-items:center;justify-content:space-between;font-size:calc(12px + var(--font-boost,0px));font-weight:900;letter-spacing:.08em;text-transform:uppercase;color:rgba(255,255,255,.26);padding:11px 11px 7px;flex-shrink:0;}
#gal-media-scroll{flex:1;overflow-y:auto;overflow-x:hidden;padding:4px 8px 10px;scrollbar-width:thin;scrollbar-color:rgba(255,255,255,.15) transparent;}
#gal-media-scroll::-webkit-scrollbar{width:4px;}
#gal-media-scroll::-webkit-scrollbar-thumb{background:rgba(255,255,255,.15);border-radius:2px;}
#gal-media-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px;align-content:start;grid-auto-rows:auto;}
.gal-mcard{position:relative!important;border-radius:7px;overflow:hidden;height:88px!important;cursor:grab;background:#111318;border:1px solid rgba(255,255,255,.10);transition:border-color .12s;user-select:none;flex-shrink:0;contain:strict;}
.gal-mcard:hover{border-color:rgba(230,87,99,.45);}
.gal-mcard.gal-dragging{opacity:.25;}
.gal-mcard video{position:absolute!important;top:0!important;left:0!important;width:100%!important;height:100%!important;object-fit:cover!important;display:block!important;pointer-events:none!important;max-width:100%!important;max-height:100%!important;}
.gal-mcard img{position:absolute!important;top:0!important;left:0!important;width:100%!important;height:100%!important;object-fit:cover!important;display:block!important;pointer-events:none!important;max-width:100%!important;max-height:100%!important;}
.gal-mbadge{position:absolute;bottom:3px;right:3px;padding:2px 5px;border-radius:3px;font-size:calc(11px + var(--font-boost,0px));background:rgba(0,0,0,.82);color:#fff;pointer-events:none;z-index:2;line-height:1;}
.gal-empty{grid-column:1/-1;color:rgba(255,255,255,.24);font-size:calc(14px + var(--font-boost,0px));text-align:center;padding:28px 0;line-height:1.7;}
#gal-pager{display:flex;align-items:center;justify-content:center;gap:8px;padding:8px;border-top:1px solid rgba(255,255,255,.06);flex-shrink:0;}
#gal-pager button{all:unset;min-width:26px;height:26px;padding:0 7px;border-radius:6px;border:1px solid rgba(255,255,255,.12);background:rgba(255,255,255,.04);color:rgba(255,255,255,.60);font-size:calc(13px + var(--font-boost,0px));font-weight:700;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all .12s;}
#gal-pager button:hover:not(:disabled){background:rgba(255,255,255,.10);color:#fff;}
#gal-pager button:disabled{opacity:.20;cursor:default;}
#gal-page-lbl{font-size:calc(13px + var(--font-boost,0px));font-weight:700;color:rgba(255,255,255,.45);min-width:60px;text-align:center;}
#gal-showcase{flex:1;display:flex;flex-direction:column;overflow:hidden;min-width:0;}
#gal-ctrl-wrap{display:flex;align-items:center;gap:8px;}
.gal-cbtn{all:unset;width:24px;height:24px;border-radius:6px;border:1px solid rgba(255,255,255,.12);background:rgba(255,255,255,.05);color:#edf0f7;font-size:15px;font-weight:700;cursor:pointer;display:flex;align-items:center;justify-content:center;transition:all .12s;line-height:1;flex-shrink:0;}
.gal-cbtn:hover:not(:disabled){background:rgba(255,255,255,.12);}
.gal-cbtn:disabled{opacity:.18;cursor:default;}
#gal-slot-lbl{font-size:calc(12px + var(--font-boost,0px));font-weight:700;color:rgba(255,255,255,.50);min-width:46px;text-align:center;}
#gal-slots{flex:1;height:0;display:grid;gap:7px;padding:5px 11px 9px;overflow:hidden;min-height:0;}
.gal-slot{position:relative!important;border-radius:9px;overflow:hidden;background:#080808;border:1.5px dashed rgba(255,255,255,.11);transition:border-color .12s,background .12s;min-height:0!important;min-width:0!important;width:100%!important;height:100%!important;}
.gal-slot.gal-slot-full{border-style:solid;border-color:rgba(255,255,255,.18);}
.gal-slot.gal-drop-over{border-color:#e65763!important;border-style:solid!important;background:rgba(230,87,99,.08)!important;}
.gal-slot.gal-dragging{opacity:.25;}
.gal-slot-empty{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;pointer-events:none;z-index:1;}
.gal-slot-plus{font-size:calc(22px + var(--font-boost,0px));color:rgba(255,255,255,.13);line-height:1;}
.gal-slot-hint{font-size:calc(11px + var(--font-boost,0px));color:rgba(255,255,255,.15);font-weight:600;}
.gal-slot-media{position:absolute!important;top:0!important;left:0!important;right:0!important;bottom:0!important;width:100%!important;height:100%!important;z-index:1!important;pointer-events:none!important;background:#080808;}
.gal-slot-media video,.gal-slot-media img{position:absolute!important;top:0!important;left:0!important;right:0!important;bottom:0!important;width:100%!important;height:100%!important;object-fit:contain!important;display:block!important;pointer-events:none!important;max-width:100%!important;max-height:100%!important;}
.gal-slot-rm{position:absolute!important;top:7px!important;right:7px!important;bottom:auto!important;left:auto!important;z-index:30!important;width:22px!important;height:22px!important;border-radius:5px!important;background:rgba(230,87,99,.88)!important;color:#fff!important;font-size:15px!important;font-weight:900!important;cursor:pointer!important;display:flex!important;align-items:center!important;justify-content:center!important;line-height:1!important;opacity:0;transition:opacity .15s,background .12s;padding:0!important;margin:0!important;border:none!important;box-shadow:0 2px 6px rgba(0,0,0,.6)!important;pointer-events:all!important;}
.gal-slot:hover .gal-slot-rm{opacity:1!important;}
.gal-slot-rm:hover{background:rgba(230,87,99,1)!important;}
.gal-mute{position:absolute!important;top:7px!important;left:7px!important;bottom:auto!important;right:auto!important;z-index:30!important;width:24px!important;height:24px!important;border-radius:5px!important;background:rgba(0,0,0,.70)!important;color:#fff!important;font-size:12px!important;cursor:pointer!important;display:flex!important;align-items:center!important;justify-content:center!important;opacity:0;transition:opacity .15s,background .12s;padding:0!important;margin:0!important;border:none!important;box-shadow:0 2px 6px rgba(0,0,0,.6)!important;pointer-events:all!important;}
.gal-slot:hover .gal-mute{opacity:1!important;}
.gal-mute:hover{background:rgba(0,0,0,.95)!important;}
#gal-fs-overlay{display:none;position:fixed;inset:0;z-index:50;background:#080808;flex-direction:column;}
#gal-fs-overlay.active{display:flex;}
#gal-fs-hint{color:rgba(255,255,255,.20);font-size:calc(13px + var(--font-boost,0px));text-align:center;padding:7px;flex-shrink:0;letter-spacing:.03em;}
#gal-fs-grid{flex:1;height:0;display:grid;gap:7px;padding:4px 8px 8px;overflow:hidden;min-height:0;}
.gal-fs-slot{position:relative;border-radius:9px;overflow:hidden;min-height:0;min-width:0;background:#080808;}
.gal-fs-slot.gal-fs-empty{border:1px dashed rgba(255,255,255,.08);}
.gal-fs-slot video,.gal-fs-slot img{position:absolute!important;inset:0!important;width:100%!important;height:100%!important;object-fit:contain!important;display:block!important;}
@media(max-width:720px){
#gal-body{flex-direction:column;}
#gal-browser{width:100%;height:220px;border-right:none;border-bottom:1px solid rgba(255,255,255,.08);}
#gal-media-grid{grid-template-columns:repeat(3,minmax(0,1fr));}
#gal-hdr{padding:8px 12px;}
#gal-slots{padding:4px 7px 7px;}
}
@media(max-width:420px){#gal-media-grid{grid-template-columns:repeat(2,minmax(0,1fr));}}
</style>
<div id="gal-app"><div id="gal-hdr"><div id="gal-title">🖼 Gallery</div><div id="gal-cats-bar"><div id="gal-cats"></div></div><button id="gal-reset" title="Reset gallery">🗑 Reset</button><button id="gal-back">↩ Main Menu</button></div><div id="gal-sub-bar"><div id="gal-subs"></div></div><div id="gal-body"><div id="gal-browser"><div class="gal-panel-hdr">Library</div><div id="gal-media-scroll"><div id="gal-media-grid"></div></div><div id="gal-pager"><button id="gal-pg-prev">‹</button><span id="gal-page-lbl">1 / 1</span><button id="gal-pg-next">›</button></div></div><div id="gal-showcase"><div class="gal-panel-hdr">Showcase<div id="gal-ctrl-wrap"><button class="gal-cbtn" id="gal-dec">−</button><span id="gal-slot-lbl">1 slot</span><button class="gal-cbtn" id="gal-inc">+</button><button class="gal-cbtn" id="gal-fs-btn" title="Fullscreen">⛶</button></div></div><div id="gal-slots"></div></div></div><div id="gal-fs-overlay"><div id="gal-fs-hint">Press Esc to exit fullscreen</div><div id="gal-fs-grid"></div></div></div>
<<script>>
(function(){
var V=State.variables;
var cfg=setup.GalleryConfig||{};
var SIZES=cfg.slotSizes||[1,4,6,9];
var COLS=cfg.slotCols||[1,2,3,3];
var MAX=Math.max.apply(null,SIZES);
var PAGE_SIZE=24;
var media=setup.GalleryStore?setup.GalleryStore.load():{};
if(typeof V.GallerySlotIdx!=='number') V.GallerySlotIdx=0;
if(!Array.isArray(V.GallerySlots)) V.GallerySlots=[];
while(V.GallerySlots.length<MAX) V.GallerySlots.push(null);
var slotIdx=+V.GallerySlotIdx||0;
var slots=V.GallerySlots.map(function(s){return s||null;});
var currentCat='all';
var currentSub='all';
var currentPage=0;
function save(){V.GallerySlots=slots.slice();V.GallerySlotIdx=slotIdx;}
function typeBadge(t){if(t==='video')return'▶';if(t==='gif')return'🎞';return'🖼';}
function catOf(m){return m.category||m.label||'Other';}
function getCats(){
var seen={};
for(var k in media){var c=catOf(media[k]);if(c) seen[c]=true;}
return Object.keys(seen).sort(function(a,b){return a.localeCompare(b);});
}
function getSubs(cat){
var seen={};
for(var k in media){
var m=media[k];
if(m.category===cat&&m.label&&m.label!==cat) seen[m.label]=true;
}
return Object.keys(seen).sort(function(a,b){return a.localeCompare(b);});
}
function getMedia(){
var out=[];
for(var k in media){
var m=media[k];if(!m) continue;
if(currentCat!=='all'&&catOf(m)!==currentCat) continue;
if(currentSub!=='all'&&m.label!==currentSub) continue;
out.push(m);
}
out.sort(function(a,b){return a.src.localeCompare(b.src);});
return out;
}
function renderCats(){
var $c=jQuery('#gal-cats').empty();
var $all=jQuery('<button class="gal-cat'+(currentCat==='all'?' on':'')+'">All</button>');
$all.on('click',function(){currentCat='all';currentSub='all';currentPage=0;renderCats();renderSubs();renderMedia();});
$c.append($all);
getCats().forEach(function(cat){
var $b=jQuery('<button class="gal-cat'+(currentCat===cat?' on':'')+'">').text(cat);
$b.on('click',function(){currentCat=cat;currentSub='all';currentPage=0;renderCats();renderSubs();renderMedia();});
$c.append($b);
});
}
function renderSubs(){
var $bar=jQuery('#gal-sub-bar');
var $s=jQuery('#gal-subs').empty();
if(currentCat==='all'){$bar.removeClass('active');return;}
var subs=getSubs(currentCat);
if(!subs.length){$bar.removeClass('active');return;}
$bar.addClass('active');
var $all=jQuery('<button class="gal-sub'+(currentSub==='all'?' on':'')+'">All</button>');
$all.on('click',function(){currentSub='all';currentPage=0;renderSubs();renderMedia();});
$s.append($all);
subs.forEach(function(sub){
var $b=jQuery('<button class="gal-sub'+(currentSub===sub?' on':'')+'">').text(sub);
$b.on('click',function(){currentSub=sub;currentPage=0;renderSubs();renderMedia();});
$s.append($b);
});
}
function hardMute(v){
v.muted=true;v.defaultMuted=true;v.volume=0;
v.addEventListener('volumechange',function(){if(!this.muted||this.volume>0){this.muted=true;this.volume=0;}});
v.addEventListener('play',function(){this.muted=true;this.volume=0;});
}
function renderMedia(){
var $g=jQuery('#gal-media-grid').empty();
var items=getMedia();
var totalPages=Math.max(1,Math.ceil(items.length/PAGE_SIZE));
if(currentPage>=totalPages) currentPage=totalPages-1;
jQuery('#gal-page-lbl').text((currentPage+1)+' / '+totalPages);
jQuery('#gal-pg-prev').prop('disabled',currentPage===0);
jQuery('#gal-pg-next').prop('disabled',currentPage>=totalPages-1);
if(!items.length){$g.append('<div class="gal-empty">No media unlocked<br>in this category yet.</div>');return;}
var pageItems=items.slice(currentPage*PAGE_SIZE,(currentPage+1)*PAGE_SIZE);
pageItems.forEach(function(item){
var $card=jQuery('<div class="gal-mcard" draggable="true">');
if(item.type==='video'){
var v=document.createElement('video');
hardMute(v);
v.loop=true;v.preload='none';v.setAttribute('playsinline','');
v.src=item.src;
$card.append(v);
$card.on('mouseenter',function(){v.preload='metadata';v.play().catch(function(){});});
$card.on('mouseleave',function(){v.pause();});
} else {
var img=document.createElement('img');
img.loading='lazy';
img.src=item.src;
$card.append(img);
}
$card.append('<span class="gal-mbadge">'+typeBadge(item.type)+'</span>');
$card.on('dragstart',function(e){e.originalEvent.dataTransfer.setData('text/plain',JSON.stringify({src:item.src,type:item.type,label:item.label||'',category:item.category||'',from:'browser'}));$card.addClass('gal-dragging');});
$card.on('dragend',function(){$card.removeClass('gal-dragging');});
$g.append($card);
});
}
function forceMedia(el, fit){
var f=fit||'contain';
function apply(){
el.style.setProperty('position','absolute','important');
el.style.setProperty('top','0','important');
el.style.setProperty('left','0','important');
el.style.setProperty('right','0','important');
el.style.setProperty('bottom','0','important');
el.style.setProperty('width','100%','important');
el.style.setProperty('height','100%','important');
el.style.setProperty('min-width','0','important');
el.style.setProperty('min-height','0','important');
el.style.setProperty('max-width','100%','important');
el.style.setProperty('max-height','100%','important');
el.style.setProperty('object-fit',f,'important');
el.style.setProperty('display','block','important');
el.style.setProperty('pointer-events','none','important');
}
apply();setTimeout(apply,0);setTimeout(apply,50);setTimeout(apply,150);setTimeout(apply,400);
}
function makeSlot(idx,slot){
var $slot=jQuery('<div class="gal-slot">').attr('data-slot',idx);
if(slot){
$slot.addClass('gal-slot-full');
var isVid=slot.type==='video';
var $media=jQuery('<div class="gal-slot-media">');
if(isVid){
var v=document.createElement('video');
hardMute(v);
v.loop=true;v.setAttribute('playsinline','');v.preload='auto';v.src=slot.src;
forceMedia(v,'contain');
$media.append(v);
setTimeout(function(){v.play().catch(function(){});},80);
var muteBtn=document.createElement('button');
muteBtn.className='gal-mute';muteBtn.textContent='🔇';
var sndOn=false;
var vRef=v;
jQuery(muteBtn).on('click',function(e){
e.stopPropagation();
sndOn=!sndOn;
if(sndOn){
var nv=vRef.cloneNode(false);
nv.muted=false;nv.volume=0.6;nv.loop=true;nv.setAttribute('playsinline','');
forceMedia(nv,'contain');
vRef.parentNode.replaceChild(nv,vRef);
vRef=nv;
nv.play().catch(function(){});
} else {
vRef.muted=true;vRef.volume=0;
}
muteBtn.textContent=sndOn?'🔊':'🔇';
});
$slot.append(muteBtn);
} else {
var img=document.createElement('img');
img.src=slot.src;
forceMedia(img,'contain');
$media.append(img);
}
$slot.append($media);
var rmBtn=document.createElement('button');
rmBtn.className='gal-slot-rm';rmBtn.textContent='×';
jQuery(rmBtn).on('click',function(e){e.stopPropagation();slots[idx]=null;save();renderSlots();});
$slot.append(rmBtn);
$slot.attr('draggable','true');
$slot.on('dragstart',function(e){var s=slots[idx];if(!s) return;e.originalEvent.dataTransfer.setData('text/plain',JSON.stringify({src:s.src,type:s.type,label:s.label||'',category:s.category||'',from:'slot',slotIdx:idx}));$slot.addClass('gal-dragging');});
$slot.on('dragend',function(){$slot.removeClass('gal-dragging');});
} else {
$slot.append('<div class="gal-slot-empty"><span class="gal-slot-plus">+</span><span class="gal-slot-hint">Drag here</span></div>');
}
$slot.on('dragover',function(e){e.preventDefault();$slot.addClass('gal-drop-over');});
$slot.on('dragleave',function(e){if(!jQuery.contains($slot[0],e.relatedTarget)){$slot.removeClass('gal-drop-over');}});
$slot.on('drop',function(e){
e.preventDefault();$slot.removeClass('gal-drop-over');
var data;try{data=JSON.parse(e.originalEvent.dataTransfer.getData('text/plain'));}catch(err){return;}
if(data.from==='slot'&&typeof data.slotIdx==='number'&&data.slotIdx!==idx){var tmp=slots[idx];slots[idx]=slots[data.slotIdx];slots[data.slotIdx]=tmp;}
else if(data.from==='browser'){slots[idx]={src:data.src,type:data.type,label:data.label||'',category:data.category||''};}
save();renderSlots();
});
return $slot;
}
function renderSlots(){
var count=SIZES[slotIdx],cols=COLS[slotIdx],rows=Math.ceil(count/cols);
var $s=jQuery('#gal-slots').empty();
$s.css({'grid-template-columns':'repeat('+cols+',minmax(0,1fr))','grid-template-rows':'repeat('+rows+',minmax(0,1fr))'});
jQuery('#gal-slot-lbl').text(count+' slot'+(count>1?'s':''));
jQuery('#gal-dec').prop('disabled',slotIdx===0);
jQuery('#gal-inc').prop('disabled',slotIdx===SIZES.length-1);
for(var i=0;i<count;i++) $s.append(makeSlot(i,slots[i]||null));
}
function renderFullscreen(){
var count=SIZES[slotIdx],cols=COLS[slotIdx],rows=Math.ceil(count/cols);
var $g=jQuery('#gal-fs-grid').empty();
$g.css({'grid-template-columns':'repeat('+cols+',minmax(0,1fr))','grid-template-rows':'repeat('+rows+',minmax(0,1fr))'});
for(var i=0;i<count;i++){
(function(idx){
var slot=slots[idx]||null;
var $slot=jQuery('<div class="gal-fs-slot">');
if(slot){
if(slot.type==='video'){
var v=document.createElement('video');
hardMute(v);
v.loop=true;v.setAttribute('playsinline','');v.preload='auto';v.src=slot.src;
$slot.append(v);
setTimeout(function(){v.play().catch(function(){});},80);
} else {
$slot.append(jQuery('<img>').attr('src',slot.src));
}
} else {
$slot.addClass('gal-fs-empty');
}
$g.append($slot);
})(i);
}
}
setTimeout(function(){
renderCats();renderSubs();renderMedia();renderSlots();
jQuery('#gal-pg-prev').on('click',function(){if(currentPage>0){currentPage--;renderMedia();jQuery('#gal-media-scroll').scrollTop(0);}});
jQuery('#gal-pg-next').on('click',function(){currentPage++;renderMedia();jQuery('#gal-media-scroll').scrollTop(0);});
jQuery('#gal-dec').on('click',function(){if(slotIdx>0){slotIdx--;save();renderSlots();}});
jQuery('#gal-inc').on('click',function(){if(slotIdx<SIZES.length-1){slotIdx++;save();renderSlots();}});
jQuery('#gal-fs-btn').on('click',function(){renderFullscreen();jQuery('#gal-fs-overlay').addClass('active');});
jQuery(document).on('keydown.gal',function(e){if(e.key==='Escape'&&jQuery('#gal-fs-overlay').hasClass('active')){jQuery('#gal-fs-overlay').removeClass('active');}});
var resetArmed=false;
var resetTimer=null;
jQuery('#gal-reset').on('click',function(){
var $btn=jQuery(this);
if(!resetArmed){
resetArmed=true;
$btn.addClass('gal-confirm').text('⚠ Confirm reset?');
resetTimer=setTimeout(function(){
resetArmed=false;
$btn.removeClass('gal-confirm').text('🗑 Reset');
},3000);
return;
}
clearTimeout(resetTimer);
resetArmed=false;
$btn.removeClass('gal-confirm').text('🗑 Reset');
try{localStorage.removeItem(setup.GalleryStore.KEY);}catch(e){}
media={};
slots=slots.map(function(){return null;});
currentCat='all';currentSub='all';currentPage=0;
save();
renderCats();renderSubs();renderMedia();renderSlots();
});
jQuery('#gal-back').on('click',function(){jQuery(document).off('keydown.gal');Engine.play(String(cfg.backPassage||'Main Menu'));});
},10);
})();
<</script>><<sound "music" "music.music" true>><<passagebg>><img src="assets/img/story/searchwork/search.webp"/><</passagebg>><<InformationUiPopUp>>I have an idea for <<print $NPCLandlady.role>> and <<print $NPCLandlord.role>>, but for that I need to find some sleeping medications.
<</InformationUiPopUp>>
<<TalkMC "Medications like that, without a prescription... let's see what exists.">>
<<InformationUiPopUp>>Several results appear. I come across a shady site that sells medications online, via private channels. The page opens, with a list of medications available for purchase without a prescription.
<</InformationUiPopUp>>
<<TalkMC "The price is much higher than usual... 90$. I imagine it's due to the fact that it's without a prescription. It's not cheap but it's exactly what I need.">>
<<InformationUiPopUp>>I check the product description, everything matches what I'm looking for. Then I look at the order details.
<</InformationUiPopUp>>
<<TalkMC "Delivery in 3 to 5 business days...">>
<div class="BottomUiBarCustom">
<<BottomButton "Story">><<if $Bank >= 90>><<link "💳 Buy">><<goto "Internet">><<set $SedativesBought = true>><<set $Bank -= 90>><</link>><<else>><<link "🔒 <em>You don't have enough money in bank</em>">><</link>><</if>>
<<link "↩️ Leave">><<goto "Internet">><</link>><</BottomButton>>
</div><<sound "music" "music.music" true>><<sound "bg" "bg.empty" true>><<passagebg>><img src="assets/img/misc/home/kitchennight.webp"/><</passagebg>>
<<InformationUiPopUp>>I go into the kitchen, take a glass out of the cupboard and place it on the countertop. I open the medication box and pour a large dose into the glass. I add a bit of tap water and mix quickly with a spoon until nothing is visible anymore.
<</InformationUiPopUp>>
<<TalkMC "There, it's perfect like that.">>
<div class="BottomUiBarCustom">
<<BottomButton "Move">><<link "➡️ Exit">><<goto "HomeKitchen">><<set $SedativesGlassWater = true>><<set $LandladyChapter6Story3Played = true>><<set $Inventory.glasswater = {id:"glasswater", name:"Glass of Water", price:0, img:"assets/img/items/story/landladychapter6/water.webp", unique:true, inventory:true, bought:true, desc:"A useful item for the story.", qty:1}>><<if $Inventory.sedatives and $Inventory.sedatives.qty >= 1>><<run delete State.variables.Inventory.sedatives>><</if>><</link>><</BottomButton>>
</div><<sound "music" "music.music" true>><<sound "bg" "bg.empty" true>><<passagebg>><<if $Time !== 3>><img src="assets/img/misc/home/entrance.webp"/><<else>><img src="assets/img/misc/home/entrancenight.webp"/><</if>><</passagebg>>
<<InformationUiPopUp>>I get a notification on my phone, my package has arrived. I go outside, open the mailbox and come back inside with the parcel under my arm.
<</InformationUiPopUp>>
<<TalkMC "Finally.">>
<<InformationUiPopUp>>I go up to my room, set the parcel on my bed and open it. I check the contents, everything is there.
<</InformationUiPopUp>>
<<TalkMC "Perfect.">>
<div class="BottomUiBarCustom">
<<BottomButton "Move">><<link "➡️ Continue">><<goto "MCBedroom">><<set $LandladyChapter6Story2Played = true>><<set $SedativesDelivered = true>><<set $Inventory.sedatives = {id:"sedatives", name:"Box of Sedatives", price:0, img:"assets/img/items/story/landladychapter6/sedatives.webp", unique:true, inventory:true, bought:true, desc:"A useful item for the story.", qty:1}>><</link>><</BottomButton>>
</div><<sound "music" "music.music" true>><<sound "bg" "bg.empty" true>><<passagebg>><img src="assets/img/misc/home/livingroomnight.webp"/><</passagebg>><<set _raw = $ActiveNPC>><<if !_raw or _raw.id is undefined>>Invalid NPC.<<else>><<set _id = String(_raw.id)>><<set _key = "NPC" + _id>><<run State.temporary.npcObj = State.variables[State.temporary.key] || State.variables[_key]>><<set _npc = _npcObj>>
<<InformationUiPopUp>>We're both in the living room. I approach him and offer him the glass of water.
<</InformationUiPopUp>>
<<TalkMC "You want a glass of water?">>
<<TalkNPC _npc "Water...?">>
<<TalkMC "Yeah.">>
<<TalkNPC _npc "I... why not, thanks.">>
<<InformationUiPopUp>>I hand him the glass. He looks at it for another second before taking it.
<</InformationUiPopUp>>
<<TalkNPC _npc "It's not usual coming from you...">>
<<TalkMC "It depends on the day, I felt like being helpful today.">>
<<TalkNPC _npc "You've got some particular urges.">>
<<TalkMC "We make do with what we've got.">>
<<InformationUiPopUp>>He takes a sip, then sets the glass down on the coffee table.
<</InformationUiPopUp>>
<<TalkNPC _npc "Tell me, do you have a girlfriend right now?">>
<<TalkMC "No. Well... it's complicated.">>
<<TalkNPC _npc "Complicated.">>
<<TalkMC "Yeah.">>
<<TalkNPC _npc "I know exactly what 'complicated' means.">>
<<InformationUiPopUp>>He says that with a smile that isn't really a smile. He stares at his glass for a moment.
<</InformationUiPopUp>>
<<TalkNPC _npc "My advice, and you can do whatever you want with it. Don't trust love. Love is nice at the beginning, and then you just have someone in front of you who disappoints you every day.">>
<<TalkMC "That's optimistic...">>
<<TalkNPC _npc "It's realistic. You'll learn with time.">>
<<InformationUiPopUp>>He finishes the glass and sets it down again on the coffee table.
<</InformationUiPopUp>>
<<TalkNPC _npc "Well. Thanks for the glass of water anyway.">>
<<TalkMC "No problem.">>
<<InformationUiPopUp>>I step back, then end up leaving the room, staying just in front of the living room entrance, slightly hidden, waiting for the effect to kick in.
<</InformationUiPopUp>>
<<revealtext "wait">><<InformationUiPopUp>>After waiting a few minutes, I see him fall asleep and start snoring.
<</InformationUiPopUp>>
<<TalkMC "Good, now let's move on to the next part.">><</revealtext>>
<</if>><div class="BottomUiBarCustom">
<<BottomButton "Decision">><<revealbtn "wait" "⌛ Wait..." "moveBtn">><</revealbtn>><</BottomButton>>
<<BottomButton "Move" "moveBtn">><<link "➡️ Continue">><<goto "HomeLivingRoom">><<set $SedativesGlassWater = false>><<set $LandladyChapter6Story4Played = true>><<set $NPCLandlordSleepDrug = true>><<if $Inventory.glasswater and $Inventory.glasswater.qty >= 1>><<run delete State.variables.Inventory.glasswater>><</if>><</link>><</BottomButton>>
</div>